Merit · Product · Internal Explainer

The Seller Portal, explained

Merit sells goods it does not own. The Seller Portal is where the people who do own them list their stock, take orders, and get them out of the door. Every screen below is exported from the Seller Portal Figma file, so this is the real design, not an impression of it.

Owner: Brian Arfi Faridhi · Last updated 30 Sep 2026 · Screens from "Seller Portal - Merit" · Audience: design, new joiners, anyone briefing on the revamp

01In one minute

If you only read one section, read this one.

Merit runs branded marketplaces where members burn loyalty points on real goods. Someone has to supply those goods. Some come from Merit's own stock, but most come from third party sellers, and every one of them needs a way to say here is my product, here is my price, here is how much I have, and then a way to actually fulfil the orders that follow.

The Seller Portal is that surface. It is the seller's entire relationship with Merit: catalog in, orders out, money back. Before it existed, sellers emailed spreadsheets to the Operations team, who typed them in by hand. Average time from a seller having a product to that product being buyable was seven days.

The strategic goal for 2026 is written as "from manual oversight to automated autonomy". In plain terms: get Merit's Operations team out of the middle. Every screen in this portal exists to remove one thing a human at Merit used to do by hand.

Catalog in

Sellers list products by web form, CSV, SFTP or API. Products land in PIM, an Offer is created against the seller, and it goes live.

Orders out

Orders arrive, the seller accepts, picks, packs and ships. Who ships depends on the model in section 03.

Money back

Delivery closes the order and triggers payout. Today the payout itself is still calculated by hand, monthly.

The one thing to remember

This is not a consumer product. The primary user is a warehouse operator under time pressure, often on a shared login, often not the person who owns the account. Most design decisions in the portal follow from that single fact, and most of the friction in the product comes from forgetting it.

Read section 08 before you trust anything

Building this page from the real Figma turned up several places where the shipped design and the written specification disagree, including one that is fully inverted. Section 08 lists them. They are not nitpicks, they change what the revamp is actually for.

02Who uses it

Four roles, two of them inside Merit. Each one meets a different part of the product, which is why there is no single "the seller journey".

External · signs the contract

Seller Admin (owner)

Sets the account up, adds the catalog, sets prices, manages bank details and invites their own staff. Logs in weekly, not hourly. Cares about margin, payout and whether their products are winning the Buy Box.

External · lives in the product

Warehouse operator (picker and packer)

The heaviest user by a wide margin. Opens the order queue in the morning and works it down. Standing, often on a shared screen, frequently holding a physical box. Needs big targets, printable paper, and no ambiguity about what to do next.

External · earned status

MFN Elite seller

A trusted seller allowed to use their own couriers. Same portal, different order screen and an extra tracking step. Cannot self serve into this tier, Merit switches it on.

Internal · Merit

Ops Admin

Operates through an admin role inside the Seller Portal itself, cross tenant. Invites sellers, sets their shipping model, flips the Elite toggle, reviews the matches the AI matching engine is unsure about, and is the hub for operating physical orders across every seller. Half of what a seller sees is decided here.

Internal · Merit as seller

Merit itself (1P)

Merit sells its own goods through a Merit-owned seller account, on the same Seller Portal every third party seller uses. No separate tooling for first-party stock.

A second workflow lives in the same portal

The Digital Seller Portal is a separate workflow on the same Seller Portal codebase, for gift card and other digital sellers. A seller doing both physical and digital switches between the two at the top of the portal, and the data stays segregated. It records the commercial terms and the fulfilment route; the Fulfillment Service performs the fulfilment. E-commerce Core holds the gift card commercial terms, discount, markup, transaction fee and tenant revenue split, per tenant and per product.

03Three shipping models, and why every screen depends on them

A seller is configured to exactly one of these. It changes the order screen, the actions available, and in principle the data they can see. Read this before section 07.

ModelWho moves the boxShown in the portal asExtra steps
SPL
Standard Pick-up Logic
Merit's carrier collects from the sellerMerit Logistics (SPL)Pack, then request an AWB for pickup
FBM
Fulfilled by Merit
Merit, from Merit's own warehouseSeller is mostly out of the per order loopSend stock to Merit up front
MFN Elite
Self shipping
The seller's own fleet or courierSelf ManagedAccept, then enter courier and tracking

SPL is the default. MFN Elite is off unless an Ops Admin turns it on, and per the specification it requires a verified warehouse address in Saudi Arabia and a cancellation rate under two percent.

04Getting a seller onto the platform

Users: Ops Admin, then Seller Admin. Sellers cannot sign themselves up. Every account starts as an invitation from inside Merit.

Multi-step onboarding wizard
The onboarding wizard. A staged setup rather than one long form, which suits the fact that a new seller has to supply company details, a warehouse address and bank information before they can trade. Figma: Onboarding Flow / Multi-Step Onboarding Wizard, 1856:2057
Dashboard empty state
The empty state, which is where every seller actually begins. Worth dwelling on during the revamp: this is the first impression of the product, and the only screen whose job is to tell a seller what to do next. Figma: Hi Fi Designs / Dashboard - empty state, 787:22476
The invite screen is not in Figma

Setting a seller's default shipping method at invite time happens through the admin role in the Seller Portal, which this file does not cover. It matters because every invited seller defaults to SPL, and if they are really an MFN or FBM seller somebody has to correct it afterwards.

A warehouse is not the seller's registered address

The seller's KYB business address is never a warehouse. A warehouse is its own structured location, stored in the Identity Service address module, which the Seller Portal proxies writes to and keeps no copy of. Every warehouse carries a mandatory map pin, a pickup contact name, email and mobile, and a system location code. A seller can register many warehouses, and each warehouse can carry many offers. The Fulfillment Service mirrors every warehouse and registers it with OTO as a pickup location. Deactivating a warehouse switches off every offer linked to it, the same as zero stock does.

Deactivating a seller does not clean the catalog

Deactivating a seller auto-suspends every one of their offers. It does not remove their catalog entries; that cleanup stays a manual Ops check.

05Product upload, all five ways

User: Seller Admin. This is the largest surface in the product and the flow that replaced emailing spreadsheets to Operations. There are five distinct ways in, aimed at five sizes of seller. All five need to be designed, because a seller picks one and lives in it.

MethodWho uses itWhat it handles
1. Single web formSmall sellers, one-off additionsOne product, via a search-first wizard
2. Bulk CSVMid size, hundreds of SKUsTemplate, partial success, per-row results
3. Bulk images by URLAnyone using CSVAn images column of pipe-separated URLs, fetched asynchronously
4. SFTP dropEnterprise, 1000+ SKUsSeller's ERP writes a CSV to a dedicated folder, polled every 5 minutes
5. APITechnically integrated sellers and aggregatorsKeys, batch endpoint, status polling, rate limits, and a supplier-facing order API
All five feed the same catalog

Every listing, whatever the method, originates in the Seller Portal. A seller picks one method and lives in it, and the method changes nothing downstream: the same matching, the same offer, the same order flow.

Method 1: the single product wizard, which starts with search

The most important thing about this flow is the order of operations. It does not begin by asking for a category or product details. It begins by asking whether Merit already sells this thing.

Add Product, search for your product
Step one, and the hinge of the whole flow. "Search to see if this product is already listed by other sellers. If it exists, you can create your own offer. If not, you'll create a new listing." Search accepts product name, UPC, brand or model number. This is what makes Merit a marketplace rather than a pile of duplicate listings: the fast path is joining an existing product, not creating one. Figma: Product Upload Flow, 2110:6658

From here the flow forks, and the Figma organises it as exactly those two branches: Listing Exists and Listing Doesn't Exist.

Select a variant step
Branch A, the product already exists. A three step wizard: Select Variant, Create Offer, Review and Submit. The seller is not describing a product, they are choosing which of its five existing variants they want to sell. Note "Save Draft" sitting alongside "Continue" at every step, so a half-finished listing is a first class state rather than lost work. Figma: Product Upload Flow / Listing Exists, 2110:8629
What makes two variants the same, or different

A Variant is the Product plus the complete set of its variant axis values, colour and size for example. When a new offer collides with an existing variant, the fix is cheapest first: split into separate Products, or add an allowed value to an axis, before ever adding a new axis, and a category carries at most five axes. A new Offer never resolves a collision. A seller can never create a variant axis themselves.

Region can be a variant axis

For Smartphones, region, UAE, International, US, is itself a variant axis. One grouped PDP holds every region, and Buy Box competition happens within a region rather than across all of them.

Create offer step
Branch A continued. The offer step, where price and stock are attached to the variant. This is the moment a catalog product becomes something a seller is actually selling. Figma: Product Upload Flow / Listing Exists, 2110:8944
New listing branch
Branch B, the product does not exist yet. A longer path, because the seller now has to supply the product information Merit would otherwise already hold, and the result goes to Merit for review rather than straight live. Figma: Product Upload Flow / Listing Doesn't Exist, 2110:22902
New listing detail entry
Branch B continued. Full product detail capture. Every attribute asked for here is a reason a seller might abandon, which is precisely why branch A exists and why search comes first. Figma: Product Upload Flow / Listing Doesn't Exist, 2110:25003

Method 2: bulk CSV, and the best screen in the product

Upload results with match bands
Upload Results. Shown twice here, plain on the left and with its tooltips open on the right. Five counters across the top: Successfully Processed, Invalid or Rejected, Match Found, Possible Matches, No Match Found. Then a per-row table carrying Match Result, a numeric Confidence percentage, and a resulting Status. This single screen is where the matching engine becomes legible to a seller, and it is the strongest piece of design in the file. Figma: Bulk Upload Flow, 3059:32281

The tooltips in that screen are the clearest statement of the rules anywhere in the product:

OutcomeWhat the tooltip saysWhat happens next
Successfully processedAll mandatory attributes are present, the entry has been accepted and processedGoes live
Invalid or rejectedOne or more mandatory attributes are missing, the entry was rejected and needs correcting before re-uploadingSeller fixes and re-uploads
Match foundA matching product was found, shown with its confidence scoreOps accepts or rejects the match
Possible matchA similar product may already exist, this entry will be reviewed by the admin team to confirm the correct matchOps accepts or rejects the match
No match foundNo matching product was found, a new listing will be created after admin reviewOps reviews and creates the new listing

Matching runs in shadow mode. Every row carries a visible confidence score, but nothing goes live off that score alone: an Ops reviewer accepts or rejects every match. LiveOps sets the automation level per category, fully manual, semi-automated, or fully automated, so there is no single fixed percentage that decides for everyone. The AI team at Merit owns the matching engine.

Rejected entries view
The rejected rows, on their own tab. Separating "this failed" from "this is waiting" is the right call, because they need completely different actions from the seller. Figma: Bulk Upload Flow / Upload Results (Rejected Entries), 3391:20965
Upload history
Upload history. A seller uploading daily needs to know which file did what, and this is also the only place a past import can be re-examined. Figma: Bulk Upload Flow / Upload History, 3059:39395
Rejected and Draft are not the same thing

A row missing a critical field, price, SKU or GTIN, is Rejected and the seller must fix the file. A row missing a recommended field, description or weight, becomes a Draft, saved and finishable in the UI. Same failed import, two completely different recovery journeys.

Methods 3, 4 and 5

Bulk images ride on the CSV rather than being a separate upload: an images column holds pipe-separated public URLs, fetched asynchronously and stored under a content-addressable name so the same photo uploaded by two sellers is stored once. Links must be direct and unauthenticated, with a specific exception for public Google Drive links. Failures are per image, not per row, so a product can go live with two of its three photos.

SFTP gives enterprise sellers a folder at /sftp/seller_{id}/inventory/, polled every five minutes, with differential updates so unchanged rows are skipped and a processing report emailed back. The portal is a monitoring surface for this method, not an input one.

The API needs a developer area: sk_live and sk_test key management, webhooks, a rate limit of 100 requests per minute, and batch status polling via POST /v1/products/batch then GET /v1/batches/{id}. A separate, supplier-facing Order API lets integrated sellers work their orders by API instead of the UI. It maps onto the same states the UI uses: a pickup request means accepted and ready to ship, a cancel call with a reason code means rejected, and shipped or delivered follow from the carrier's own events.

06Price and stock

User: Seller Admin. The highest frequency catalog action by far, and the one where latency costs real money.

Products list with price and stock
The product list, which doubles as the price and stock surface. This is where a seller spends most of their non-order time. Figma: Price & Stock / Products List, 4137:52359
Products list variant
A second state of the same screen. The Price and Stock page carries eleven variants in the Figma, which is a strong hint that this screen has been iterated on more than any other, and is where the real interaction complexity sits. Figma: Price & Stock / Products List, 4139:73228
Stock behaves unusually

Stock decrements when payment is confirmed, not when the customer reaches checkout. There is no reservation or hold. Two customers can therefore both buy the last unit, and one of them fails after paying. This is known, confirmed current behaviour, and the interface has to deal with it honestly rather than pretend it cannot happen.

07Fulfilling an order

User: warehouse operator. The core loop of the product, and the screen the heaviest user spends the day in. The Figma splits it into two boards, one per shipping model.

OMS is the source of truth here

The Seller Portal does not talk to the Fulfillment Service directly. The Order Management System is the single source of truth for order and fulfilment status, and the portal shows what OMS knows.

A short reference sits next to the system order id

Every order also carries a short, human-readable reference in the form SELLER_PREFIX-YYMMDD-NNNN, for example AF-260819-0042, unique per seller per day and reset at Riyadh midnight. It is shown next to the system order id and printed on the pick and pack label, but it is never a lookup key.

New→Accepted→ Ready to ship→Shipped→Delivered
Orders list
The order queue. Where the operator starts every morning and works down. Figma: Hi Fi Designs / Orders, 1963:13370
SPL order detail, Merit Logistics
An SPL order, accepted. Shipping Partner reads Merit Logistics (SPL). The primary action is Request AWB and Ship, with the helper text "Pack the order and click Request AWB when ready for SPL pickup", so the seller signals readiness and Merit's carrier takes over. Note the right hand Order Timeline, Print Items on the items card, and Special Instructions carrying handling notes. Figma: Hi Fi Designs / Orders - Merit logistics, 988:10172
Self managed order detail, masked customer
A Self Managed order, new. Two actions, Accept Order and Cancel Order, and a timeline that includes "Awaiting Acceptance" where the SPL one showed "Accepted". Customer Details here are masked: A***r R***, a****e***e.com, ******313. That is correct: every order is masked until the seller accepts it. The SPL frame above shows the details after acceptance. The build keeps them masked on SPL. Figma: Hi Fi Designs / Orders - Self managed, 133:9408
StateAllowed actionWho gets told
NewAccept, Cancel with a reason picked from a dropdown, Print itemsSeller email
AcceptedPick and pack, upload the invoice, then Request AWB (SPL) or enter tracking (Self Managed)Customer sees "Accepted"
Ready to shipHand over to carrierCustomer push notification
ShippedManual delivery override onlyCustomer sees courier and tracking
DeliveredNone, order is closedPayout triggered
Delivery can close itself

An order becomes Delivered when the customer taps "Received" in the B2C app, or automatically after seven days with no dispute raised. That auto close is what makes payout possible without a human confirming every parcel.

The biggest missing screen

After bulk accepting a batch of orders, the operator is returned to the order list with no indication of what to do next, and has to open each order individually. The proposed fix is a preparation view: the accepted batch on one scrollable surface, each card showing order, tenant, item, SKU, quantity and packing notes, markable as packed without navigating away, resumable if they leave. It is not in the Figma and it is the highest value gap in the product.

08Where the design and the specification disagree

Found by building this page from the Figma and the PRDs side by side. Each of these needs a decision, and each one changes what the revamp is for.

Contradiction

1. The API assumes a sandbox that does not exist

The upload specification offers sellers an sk_test sandbox key. There is no Seller Portal sandbox environment; it was deferred with the wider sandbox effort, which is also why the design team has to be given staging accounts instead.

Drift

2. Two visual languages in one file

The product upload screens use a dark navy application header. The order screens use a white header with a left navigation rail carrying text labels. These are different design eras sitting in the same product, and any revamp has to pick one deliberately rather than inherit both.

Coverage

3. Large parts of the product were never designed

No design exists for: the SFTP monitoring surface, the developer and API area, bulk image partial-failure states, the admin role's own screens, the printed pick list, the post-bulk-accept preparation view, self-service returns, or a settlement and payout view. Some of this is a redesign and some is original design, and those are different kinds of work to plan for.

09Design constraints

The constraints that will bite, and are not obvious from the screens alone.

Rules that come from the specification, not from taste

10Glossary

The words that come up constantly and mean something specific here.

SPL
Standard Pick-up Logic. Merit's carrier collects from the seller. Appears in the portal as "Merit Logistics (SPL)". The default for every new seller.
FBM
Fulfilled by Merit. The seller ships stock to Merit's warehouse in advance and Merit fulfils to the customer.
MFN Elite
Self shipping, shown as "Self Managed". A trusted seller uses their own courier and enters their own tracking. Off by default, admin enabled.
AWB
Air Waybill, the carrier's shipping document. On an SPL order the seller requests one once the parcel is packed, which is how they tell Merit it is ready for pickup.
Tenant
The branded marketplace an order came from: Al Fursan, SAIB, Saudia, Kantar. It decides packaging and inserts, which is why operators need it visible before packing.
Offer
A seller's price and stock against a catalog product. Several sellers can hold offers on the same product, which is what makes it a marketplace.
Variant
A Product plus the complete set of its variant axis values. A category carries at most five axes. A collision between two variants is resolved by splitting into separate Products or extending an axis's allowed values, never by creating a new Offer, and never by a seller adding their own axis.
Warehouse
A structured pickup location a seller registers, held in the Identity Service address module, not the seller's KYB business address. Carries a map pin, a pickup contact, and a system location code. A seller can hold many, each offer belongs to one, and deactivating a warehouse switches off every offer linked to it.
1P
First party. Merit selling its own goods through a Merit-owned seller account, on the same Seller Portal every third party seller uses.
Digital Seller Portal
A second workflow on the same Seller Portal codebase, for gift card and other digital sellers, data segregated from physical selling. Records commercial terms and fulfilment route; the Fulfillment Service performs the fulfilment.
Order reference
A short, human-readable id in the form SELLER_PREFIX-YYMMDD-NNNN, unique per seller per day, reset at Riyadh midnight. Shown next to the system order id and printed on the pick and pack label. Never a lookup key.
Buy Box
The winning offer shown by default on a product page. Chosen on trusted stock, availability, total price including shipping, and seller cancellation rate. For a category where region is a variant axis, such as Smartphones, the competition happens within a region, not across all of them.
PIM
Product Information Management, built on MedusaJS. Holds product data, separate from price and stock.
Match Found, Possible Match, No Match Found
The three outcomes of identity resolution on upload. Each carries a visible confidence score. Matching runs in shadow mode: an Ops reviewer accepts or rejects every match, and LiveOps sets the automation level per category rather than one fixed threshold deciding for everyone.
Source Authority Scoring
How conflicting product data is resolved. Merit retail scores 100, a brand owner 90, an authorised distributor 70, a marketplace seller 50. Higher wins. This is why a seller's description can silently not appear.
Merchant of Record
Merit is the legal seller to the customer, which is why the seller does not own the customer relationship and why masking is legitimate rather than obstructive.