The marketplace
XGM_KERNEL=amazon runs the desk's market as one continuous online marketplace with a fulfilment network, seen
from the seat of a third-party wholesale seller: you buy products from suppliers, ship them into the fulfilment
network, set your own prices (or let the default repricer do it), and the network sells, ships and returns them
hour by hour, charging the marketplace's published fee card. The money is held in a seller balance and released
to your cash by settlement statements. The manual wholesale cart and trade-enabled agent carts follow this delivery flow. Owned goods are created by
removing received stock; instant purchases of new distributor goods are unavailable. The console, payments and
exchange remain available with the permissions described in their documentation.
One market and the marketplace clock
There is one market, the US Marketplace (id us). It runs on a marketplace clock: one tick is one
marketplace hour, and the clock runs XGM_TIME_SCALE times faster than real time β by default 24, so one real
hour is one marketplace day, a marketplace week passes in 7 real hours and a tick closes every 2 minutes 30 seconds
of real time (interval "2m30s"). At time scale 1 the marketplace runs in real time. Every date the marketplace
shows is a marketplace date: tick t opens at the marketplace's epoch (2026-01-01 00:00, a Thursday) + t hours, and
the market's seasons (the peak surcharge, fourth-quarter storage, slow receiving) follow the weeks of that marketplace
year. A marketplace day runs from midnight to midnight: ticks 24d to 24d + 23 are day d.
GET /api/v1/markets/us says where the clock is: current_tick, tick_sim_at (the marketplace date and time the
open hour began), sim_now, time_model: "continuous", ticks_per_day: 24, time_scale, and when the open hour
closes in real time (tick_closes_at, seconds_to_close). The menu, history and tape rows, orders and the record carry
sim_at next to their tick. Things a person must act on stay in real time: an order's payment deadline
(closes_at), the notice of a fee amendment, the monthly participation fee, payouts and refunds of real money, and
the terms.
What happens every marketplace hour (at the close of each tick):
- new supplier offers appear (each stays open for days, below) and the desk decides on each once, when it appears;
- every order paid in this hour or before fills as a lot; unpaid orders whose payment window or offer ended expire;
- for every account's stock: lots due arrive (and become sellable), removals requested this hour are carried out,
the price in effect meets the hour's buy box and the stock sells its share of the hour's sales, first in first
out; customer refunds and returned units due this hour are worked. The money of these events accrues on the
lot (
accrued_today, by kind) until the day closes.
What happens at the end of every marketplace day (the close of its last hour, 23:00β24:00):
- each lot's money of the day is posted to the seller balance β one ledger entry per lot and kind (
sale_credit,referral_fee,fulfilment_fee, β¦, noteday N) β together with the day's storage, aged-inventory and utilization charges of its on-hand units; - the record gets its daily entries (units sold and the buy box of the day), and lots with nothing left and no return still on its way settle;
- every 14th day, settlement statements release the seller balance (below).
Until a day closes, what a lot earned that day shows as accrued_today on GET /api/v1/positions and on the stock
view; its cash_flows, pnl_so_far and the seller balance count posted money only.
The listings and what an offer shows
The interface separates Distributor supply (the buy side) from Sell on the marketplace (the sell side). The distributor board has one row for every catalogue product, including products with 0 available units. It aggregates the units currently quoted by distributors, the available price range, and the best orderable quote's minimum order and order increment. Open a product to compare its individual distributor quotes. The marketplace board shows the listing's current Buy Box, delayed best sellers rank (BSR), rank drops and seller count. A product's page charts the public price, BSR and seller-count history, even while the product is unavailable from distributors.
The market itself is the wholesale market's: about a thousand listings in twelve categories, built on real FMCG
products of a real wholesale seller's assortment (real titles, brands, product types, reference prices, size tiers
and case packs; every ASIN, MSKU, FNSKU and UPC lightly altered, so none is a real identifier; no real sales, sellers or
costs). Products ramp up, sell and phase out over years; a listing's next product takes over under a new SKU. Each
listing carries its category's typical crowd of competing sellers with their repricers, a changing Buy Box price and a sales rank among the products of the marketplace category.
Published prices and seller counts include eligible received participant offers. Exact customer demand and other
sellers' policies are not published; use the observed listing history and your own seller reports. The categories' demand seasons follow
the marketplace calendar like the fee seasons. The rank is published an hour late (rank_as_of); sales_rank_avg
and rank_drops cover the last 30 days, rank_drops_long the last 90. Sales velocities are never published, in
any form.
A deal is a supplier's offer of a product (a single item, a multipack or a bundle). Offers appear at every hour and
stay open for days β from one day to three weeks, never beyond the product's time on the listing; the menu
(GET /api/v1/markets/us/deals) shows every offer open now, each viewed at the current hour. The offer's terms
(unit_cost, max_qty, minimum_order, order_increment) are fixed for that batch; the next batch may quote different
prices, quantities and order terms. Its remaining available_units fall as buyers reserve or purchase stock: the
account holders, and the marketplace desk, which buys some of the batches it likes from the same stock within a day
and a half of their appearance (an order placed before the desk's leaves it less; a batch can sell out). Its
facts (the buy box, signals, fees, lead time, net margin) are
those of the current hour. Besides the wholesale facts (unit_cost, list_price = the hour's buy box price,
sales_rank, rank_as_of, sales_rank_avg, rank_drops, rank_drops_long, nsellers, sku, asin, msku,
fnsku, upc, family, listing_type, category, category_code, brand, pack, case_pack, max_qty) it shows:
| field | meaning |
|---|---|
key, tick |
the offer's key (us-<hour it appeared>-<n>) and the hour it appeared |
distributor_id, distributor_name |
the supplier quoting this batch |
available_units |
currently available distributor units, after active order reservations and purchases; may be zero |
minimum_order, order_increment |
order at least the minimum, then add whole increments: qty = minimum_order + n Γ order_increment for a nonnegative integer n, within available stock |
valid_until, hours_left, sim_valid_until |
the first hour it is no longer open (a tick), the marketplace hours left, and that time as a marketplace date |
size_tier |
small_standard, large_standard, small_bulky or large_bulky (from the product's weight and dimensions) |
unit_weight_lb, dimensions_in, cubic_feet, shipping_weight_lb |
the product's physicals (below) |
units_per_carton |
units in one inbound carton |
prep |
{label, kit, per_unit}: whether the unit needs a label (and kitting, for multipacks and bundles) and the seller-side prep charge per unit (below) |
referral_rate, referral_fee, referral_min |
the referral fee at the buy box price (the rate is the fee / price, the minimum included) |
fulfilment_fee, fulfilment_base, peak_surcharge, fuel_surcharge |
the fulfilment fee per unit sold at the buy box price this hour, and its parts |
fba_fee |
the same fulfilment fee (the key the wholesale pages read) |
fees_at_price |
referral + fulfilment per unit sold at the buy box price |
storage_per_day, storage_per_month |
the storage of one unit on hand for a marketplace day (and a month), at this week's rate |
peak_season, fee_schedule |
whether the peak surcharge applies this week; the fee schedule version in force |
inbound_route, inbound_per_unit |
the default route and its inbound cost per unit for the offer's max_qty |
inbound_routes[] |
every route: {route, label, available, per_unit, lead_typical, lead_max, reason?}, lead times in days |
lead_time |
{typical, min, max, distribution, unit: "days"}: the product's lead time in days by the default route for an order filled now |
return_threshold |
the category's returns-processing threshold (below) |
net_margin |
list_price β fees_at_price β unit_cost β inbound_per_unit: before storage, returns and anything unsold |
GET /api/v1/markets/us β rules publishes the whole rule book: the fee schedule in force (rules.fees.schedule,
its schedule_version and digest), storage per cu ft and month and day, the categories with their referral tiers and
return thresholds, the calendar of the marketplace year, the inbound routes and lead times in days, the stock, pricing
and payout rules in days and hours, the capacity rule and the pending fee amendments.
Buying: the payment window and the fill
You order an open offer (POST /api/v1/orders or a cart line) with a quantity, an inbound route and, if you like, a
starting pricing rule. The account holder's own cart is a wholesale trade cart: products bought there enter the
inbound/receipt/selling lifecycle, including delivery charges. Add a quote from its product page, review the route
and starting pricing rule in the cart, and fund the order at checkout. The quantity must satisfy the distributor's minimum and increment and fit its current
available_units. The stock belongs to the batch and is shared across buyers: it cannot be sold repeatedly to
different accounts. Cart proposals do not reserve stock. An order awaiting payment reserves its quantity until its
payment window expires or the order is cancelled; paid and filled orders permanently consume the batch. The
order is a reservation: it must be paid within one real hour of placing it and while its offer is still open,
whichever comes first β closes_at is the real time that window ends and expires_tick the first marketplace hour
starting at or after it. Once paid (the hour it was paid in is its paid_tick), it fills at the close of that
marketplace hour as a lot, at the offer's unit cost plus the route's inbound fee. An unpaid order expires at the
close of the hour before expires_tick. The fulfilment-network capacity (below) is checked when you order and again
when you pay, before any money moves (a card is charged, or a hosted payment opened, only once it fits); a payment
confirmed by the provider is never refused for capacity.
The fee card
The fees below are the defaults (2026 approximations of a large marketplace's US fee card, in the desk's currency).
The schedule in force is always the one in rules.fees.schedule; it changes only by announced amendments (below).
Per-event fees are rounded to the cent per unit; storage, aged-inventory and utilization charges accrue hour by hour
on the units on hand and are posted once a day in whole cents (the fraction of a cent is carried to the next day, so
a month of daily charges adds up to the month's charge).
Referral fee β per unit sold
A share of the whole sale price at the rate of the tier the price falls in (so a price just over a tier's limit pays the higher rate on all of it), never less than the minimum per unit:
| category | rate | minimum |
|---|---|---|
Grocery & Gourmet Food (GRO) |
8 % up to 15.00, 15 % above | none |
Beauty & Personal Care (BPC), Health & Household (HHS), Baby Products (BAB) |
8 % up to 10.00, 15 % above | 0.30 |
Automotive (AUT) |
12 % | 0.30 |
every other category (TLS, ACS, OFF, PET, HOM, GAR, SPO) |
15 % | 0.30 |
For example, grocery at 15.00 pays 1.20 and at 15.01 pays 2.25; beauty at 3.00 pays the 0.30 minimum.
Fulfilment fee β per unit sold
By size tier, shipping weight and the sale price's band (under 10.00 / 10.00β50.00 / over 50.00). The shipping weight is the unit weight for small standard; for the other tiers the greater of the unit weight and the dimensional weight (length Γ width Γ height / 139, bulky sides counted at least 2 in).
| small standard, up to | < 10 | 10β50 | > 50 |
|---|---|---|---|
| 2 oz (0.125 lb) | 2.43 | 3.32 | 3.58 |
| 4 oz | 2.50 | 3.39 | 3.65 |
| 6 oz | 2.56 | 3.45 | 3.71 |
| 8 oz | 2.67 | 3.57 | 3.83 |
| 10 oz | 2.77 | 3.68 | 3.94 |
| 12 oz | 2.83 | 3.77 | 4.03 |
| 14 oz | 2.89 | 3.87 | 4.13 |
| 1 lb | 2.95 | 3.96 | 4.22 |
| large standard, up to | < 10 | 10β50 | > 50 |
|---|---|---|---|
| 0.25 lb | 2.91 | 3.73 | 3.99 |
| 0.5 lb | 3.20 | 4.02 | 4.28 |
| 0.75 lb | 3.49 | 4.31 | 4.57 |
| 1 lb | 3.78 | 4.60 | 4.86 |
| 1.25 lb | 4.10 | 4.92 | 5.18 |
| 1.5 lb | 4.43 | 5.25 | 5.51 |
| 1.75 lb | 4.75 | 5.57 | 5.83 |
| 2 lb | 4.97 | 5.79 | 6.05 |
| 2.25 lb | 5.19 | 6.01 | 6.27 |
| 2.5 lb | 5.41 | 6.23 | 6.49 |
| 2.75 lb | 5.63 | 6.45 | 6.71 |
| 3 lb | 5.85 | 6.67 | 6.93 |
| 20 lb | 6.15 + 0.08 per started 0.25 lb above 3 lb | 6.97 + 0.08 β¦ | 7.23 + 0.08 β¦ |
| bulky, up to 50 lb | < 10 | 10β50 | > 50 |
|---|---|---|---|
| small bulky | 6.73 + 0.38 per started lb above 1 lb | 7.55 + 0.38 β¦ | 7.81 + 0.38 β¦ |
| large bulky | 8.53 + 0.38 per started lb above 1 lb | 9.35 + 0.38 β¦ | 9.61 + 0.38 β¦ |
Peak surcharge from mid-October to mid-January (weeks 41 to 1 of the marketplace year inclusive, counted 0β51 as
rules.calendar.week_of_year from the marketplace date: week 0 is 1β7 January, week 51 runs from 24 to 31 December): small standard +0.19 up to 0.25 lb,
+0.23 up to 1 lb; large standard +0.26 up to 1 lb, +0.33 up to 3 lb, +0.48 up to 20 lb; small bulky +0.80; large bulky
+1.30. A fuel and logistics surcharge of 3.5 % applies to the base fee and the peak surcharge. Example: a
small-standard unit of 0.1 lb sold at 8.00 pays 2.52 (2.71 in peak season), at 12.00 pays 3.44.
Storage β per cubic foot of units on hand
| JanuaryβSeptember | OctoberβDecember (weeks 39 to 51) | |
|---|---|---|
| standard tiers | 0.78 per cu ft and month | 2.40 |
| bulky tiers | 0.56 | 1.40 |
Storage is charged per marketplace day on the units on hand hour by hour (from the hour a lot arrives to the hour
its units leave): cu ft Γ the month's rate Γ 12 / 365 a day. A 0.1 cu ft standard unit pays 0.0026 a day off-season
and 0.0079 in the fourth quarter. The rate follows the week of the marketplace year (rules.calendar);
rules.fees.storage_per_cuft_day publishes the day's rate.
Aged-inventory surcharge, on top of storage, by the age of the units since they arrived (per cu ft and month; from a year on at least a minimum per unit and month):
| age (days) | 181β210 | 211β240 | 241β270 | 271β300 | 301β330 | 331β365 | 366β455 | 456 + |
|---|---|---|---|---|---|---|---|---|
| per cu ft / month | 0.50 | 1.00 | 1.50 | 5.45 | 5.70 | 5.90 | 6.90 (min 0.30 / unit) | 7.90 (min 0.35 / unit) |
The age is the lot's whole marketplace days in stock at the end of the day.
Storage utilization surcharge, on top of storage, when the account's stock is slow for its sales: the weeks of supply = the average cu ft on hand over the last 90 days / the average cu ft shipped per week over them. Above 22 weeks every unit on hand pays per cu ft and month:
| weeks of supply above | 22 | 28 | 36 | 44 | 52 |
|---|---|---|---|---|---|
| standard tiers | 0.44 | 0.76 | 1.16 | 1.58 | 1.88 |
| bulky tiers | 0.23 | 0.46 | 0.63 | 0.76 | 1.30 |
Exempt: accounts storing under 25 cu ft on average, and accounts within 52 weeks (364 days) of their first lot on the market.
The monthly invoice view. Storage, aged-inventory and utilization charges are posted daily; the stock view
(GET /api/v1/stock β invoices, and the console) groups them by marketplace month:
{account_id, market, month ("YYYY-MM"), days, from_tick, to_tick, by_kind, total}.
Low-inventory-level fee β per unit shipped
When a SKU's days of supply run short β days of supply = the unit-days on hand / the units shipped, over the last 30 days and over the last 90 (today's hours included), taking the greater of the two β every unit shipped pays:
| days of supply under | 14 | 21 | 28 |
|---|---|---|---|
| small standard (up to 1 lb) | 0.89 | 0.63 | 0.32 |
| large standard up to 3 lb | 0.97 | 0.70 | 0.36 |
| large standard up to 20 lb | 1.11 | 0.87 | 0.47 |
| small bulky | 1.85 | 1.02 | 0.51 |
| large bulky | 2.09 | 1.15 | 0.57 |
Exempt while the SKU shipped fewer than 20 units over the last 7 days, for a new product β within 26 weeks (182 days) of the first arrival of the SKU on the account, however often it sold out since β and for a new seller: within 52 weeks (364 days) of the account's first lot on the market. Keeping stock in the pipeline avoids it; keeping too much brings the storage and utilization charges.
Removal and disposal β per unit
| shipping weight up to | 0.5 lb | 1 lb | 2 lb | above 2 lb |
|---|---|---|---|---|
| standard tiers | 0.84 | 1.53 | 2.27 | 2.89 + 1.06 per started lb above 2 lb |
| shipping weight up to | 1 lb | 2 lb | 4 lb | 10 lb | above 10 lb |
|---|---|---|---|---|---|
| bulky tiers | 3.12 | 4.43 | 6.82 | 10.12 | 13.84 + 1.06 per started lb above 10 lb |
Disposal costs the same as removal by default (its own table in the schedule).
Returns β refund administration and returns processing
When a customer returns a unit, the sale price is refunded (refund), the referral fee is refunded
(referral_refund) less the refund administration fee β 20 % of that referral fee, at most 5.00 per unit
(refund_admin_fee) β and the fulfilment fee is not refunded.
Returns processing fee, per returned unit: charged only on a SKU whose return rate over the last 28 days (returned / shipped) is above its category's threshold, with at least 25 units shipped in that window, and only for the returns above the threshold.
| category | GRO | OFF | BPC | HHS | GAR | HOM | TLS | SPO | AUT | BAB | PET | other |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| threshold | 2.9 % | 4.4 % | 5.5 % | 5.5 % | 7.7 % | 8.1 % | 8.7 % | 8.7 % | 9.1 % | 9.3 % | 10.2 % | 4.8 % |
The fee: small standard 1.78 / 1.89 / 2.05 / 2.21 up to 0.25 / 0.5 / 0.75 / 1 lb; large standard 2.36 / 2.62 / 2.89 / 3.15 / 3.62 up to 0.5 / 1 / 1.5 / 2 / 3 lb, then 3.91 + 0.07 per started lb above 3 lb; bulky tiers the fulfilment fee's base at the unit's price band.
Inbound β charged with the order
The order debit is the units at unit_cost plus the inbound fee per unit of the route you choose (the order's
fee_amount):
- carrier: parcel and express charge per billable lb (the greater of the weight and the dimensional weight at 1,728 / 139 lb per cu ft) plus per carton (every carton shipped, a partial last one too: cartons = units Γ· units per carton, rounded up), with a minimum per unit; LTL charges per pallet (pallets = units Γ cu ft Γ 1.15 / 60, at least one);
- placement: free ("optimized") from 5 identical full cartons, otherwise the minimal-split fee per unit (small standard 0.21 / 0.25 / 0.30 up to 0.375 / 0.75 / 1 lb; large standard 0.30 / 0.38 / 0.47 / 0.60 / 0.85 / 1.20 up to 0.75 / 1.5 / 3 / 5 / 12 / 20 lb; bulky 1.60 / 2.60 / 3.90 / 5.10 / 6.50 up to 5 / 12 / 28 / 42 / 50 lb);
- seller-side prep for units that need a label: 0.30 small standard, 0.40 large standard, 0.60 small bulky, 0.75 large bulky, plus 0.35 for kitting (multipacks and bundles). The marketplace offers no prep or labelling service under the 2026 rules: this is what a prep service charges you to label and kit the units before they ship, collected with the order so the order shows its whole landed cost (it is not a marketplace fee; its days are part of the lead time).
Shipments may arrive with a defect (labels, packaging, carton contents): the route's defect risk is 1 % for
parcel, 5 % for express and 3 % for LTL, and a defective shipment pays an inbound_defect_fee per unit when it
arrives (small standard 0.32; large standard 0.42 / 0.62 / 1.74 up to 1 / 3 / 20 lb; bulky 2.50). Now and then a
lot loses part of its units in the network; they never become sellable. Units lost on a partnered route
(parcel, ltl) are reimbursed when the lot arrives, at their landed cost (unit cost + inbound per unit), as a
reimbursement credit to the lot; on your own carrier (express) the loss is yours.
Product physicals
Every product has a weight, dimensions, a size tier and a carton, synthesized deterministically (no real measurements): from the title's net content where it states one (ounces, fluid ounces, pounds, grams, millilitres, "Pack of N", β¦), packed densely like the packaged goods it is, and otherwise from the size tier's typical weights and densities. One product has one size everywhere; a multipack weighs its units plus packaging, a bundle its parts. The tiers:
| tier | weight | longest Γ median Γ shortest side |
|---|---|---|
| small standard | β€ 1 lb | β€ 15 Γ 12 Γ 0.75 in |
| large standard | β€ 20 lb | β€ 18 Γ 14 Γ 8 in |
| small bulky | β€ 50 lb | β€ 37 Γ 28 Γ 20 in, length + girth β€ 130 in |
| large bulky | β€ 50 lb | β€ 59 Γ 33 Γ 33 in, length + girth β€ 130 in |
Units per carton: the supplier's case pack where there is one (multipacks: the case pack Γ· the pack), otherwise as many units as fit 1.5 cu ft and 50 lb; one per carton for bulky units. Units need a marketplace label unless the product ships under its manufacturer's barcode (its FNSKU is its ASIN); multipacks and bundles need a label and kitting.
Inbound routes and lead times
| route | cost | eligible | defect risk | |
|---|---|---|---|---|
parcel |
partnered parcel (default) | 0.40 per billable lb + 1.00 per carton, at least 0.15 per unit | always | 1 % |
express |
express, own carrier | 1.10 per billable lb + 2.50 per carton, at least 0.40 per unit | always | 5 % |
ltl |
partnered LTL pallets | 225.00 per pallet | from 5 identical full cartons | 3 % |
A lot's lead time, in days from the hour its order fills, is the supplier's processing (7 days) + dispatch (0β3 days) + prep (0β2 days, for labelled or kitted units) + transit + receiving at the fulfilment centre + now and then a delay (6β14 extra days on 15 % of lots, 12β20 on 4 %), the trip capped at 28 days (35 for LTL; 49 / 56 in peak season). The lot becomes eligible to sell when received: fill hour + 24 Γ the lead days, plus any supplier processing spread in hours included in the arrival window. Receipt does not guarantee an immediate sale. By the default route, for a labelled unit off peak, lead times run 9β35 days, typically 12:
| lead time (days) | β€ 14 | β€ 21 | β€ 28 |
|---|---|---|---|
| share of lots (parcel, labelled, off peak) | 62 % | 86 % | 97 % |
Express is faster (71 % within 14 days), LTL slower (11β42 days, typically 15). From mid-October to the end of the
year the fulfilment centres receive slowly: lead times run 15β56 days (typically 23; LTL up to 63). An offer's
lead_time and inbound_routes[] give the distribution for that product for an order filled now;
GET /api/v1/markets/us/deals/{key}/inbound?qty= quotes every route for a quantity (below). The drawn lead time is
revealed when the lot arrives; until then you know its window (arrives_window in ticks, arrives_window_days).
Example (a large-standard unit of 1.2 lb and 0.08 cu ft, 6 per carton, labelled): 30 units by parcel 1.05 per unit (optimized placement); 24 units by parcel 1.43 (4 cartons: minimal split); 30 by express 2.14; 30 by LTL 7.90 (one pallet for 30 units); LTL is not available for 24.
Your stock and your price
A paid order fills at the close of its paid hour as a lot on the account's trading account. The lots of one SKU form the account's stock of it: once a lot arrives it sells, first in, first out (the oldest lot first), at your price, hour by hour, for as long as it takes β there is no horizon. A lot is
- inbound while in transit: it sells nothing and pays no storage;
- on hand from its arrival hour: it sells, pays storage and ages;
- awaiting returns when it has no unit left but customer returns of its sales are still on their way;
- settled at the end of the first day on which nothing is left and every return has come back: its
realized_pnl= its cash flows β its cost basis, exactly as its trade on record shows.
Pricing rules
You set a pricing rule per market and MSKU, at any time; it takes effect from the next marketplace hour
(effective_from_tick: the hour already running keeps the price it opened with, and past hours never change). The
kinds:
| kind | price | parameters |
|---|---|---|
default (or no rule) |
the default repricer: the Buy Box of the other offers, never under your break-even, never over 2 Γ the newest lot's list price | none |
featured_offer |
follows the Buy Box of the other offers: buy box Γ (1 + offset_pct) + offset |
offset, offset_pct (β0.9 β¦ 1.0), min_price (required), max_price |
fixed |
your price | price, min_price (required), max_price |
beat_lowest |
an alias of featured_offer that many under the buy box: {"kind": "beat_lowest", "offset_pct": 0.03} = 3 % under |
as featured_offer, non-negative |
Every price is clamped to [min_price, max_price] and rounded to the cent. The break-even of the default repricer
is the lowest price from which every higher price covers the unit-weighted landed cost of your units on hand (unit
cost + inbound) after the referral and fulfilment fees (it accounts for the referral tiers' cliffs and the price bands);
a product that no price covers is not offered. An order or a cart line can carry the starting rule (pricing): it
applies to the SKU from the hour after the fill if the SKU has no rule yet.
The guardrail. An offer priced above 1.5 Γ the median buy box of the product's last 13 weeks (91 days) is deactivated as a potential pricing error for that hour: it sells nothing (its price is still reported to you). An offer is also inactive without stock on hand, without a buy box price (rules that follow it), or once the product has left the listing.
Buy Box competition. A listing's customers are shared by everyone selling it: the listing's other sellers, the desk's lots and the stocked accounts. A customer buys once, from one offer β mostly from the lowest price (the Buy Box), less often from an offer a little above it, rarely from one far above it β and nobody sells more than its received stock. The other sellers run their own repricers: when an account prices under the Buy Box, most of them follow within hours (some match the lower price, some go a cent or a percent under it, a few never reprice), each down to its own floor and never above the price it asked before; when the lower offer is gone, they go back. The desk's lots follow the market like the default repricer. A lower Buy Box also draws more customers to the listing.
The Buy Box your rule follows is that of the other offers: the lowest of their prices as the hour opens (your own
offer never counts, so a rule never chases itself). A rule that beats it can start a price war, and the war ends at the
floors β yours (min_price, the break-even) and theirs: the sellers with the lower costs keep the Buy Box. The pricing
preview (GET /pricing/{market}/{msku} β preview.buy_box) shows the Buy Box your rule would follow now; the public
Buy Box and seller count of a listing show the market as it closed the last hour. There is no guaranteed sales
allocation or published rule for another seller's repricer; use the public listing signals and your own sales history to
assess the market. Inbound units cannot compete until received.
Your account records are private. Your prices, pricing rules, exact sales, stock, costs and results are available only in your authenticated account views. No public page reveals another account's or the desk's exact executions, sales or profitability.
Customer returns
A share of the units sold comes back (the share depends on the product and its category; it is not published):
- the refund 3β21 days after the sale (
refund= βunits Γ the sale price,referral_refund,refund_admin_fee, and the returns processing fee where the SKU is above its threshold); - the unit 5β14 days after the refund: sellable units go back into the stock of the lot they came from (and sell again from the next hour); unsellable ones are disposed of at the disposal fee.
Both fall on the sale's hour of the day; their money accrues and is posted at that day's close like every other.
Seller balance and disbursements
Every money flow of your lots β sale credits, fees, refunds, storage β is posted at the day close to the account's seller balance of the market, not to its cash. The seller balance is held and reaches your cash (what orders and payouts spend) only by settlement statements:
- Scheduled: every 14 marketplace days (
rules.stock.settlement_period_days), at a day close, a statement releases the entries posted up to 7 days before (funds_hold_days = 7): money reaches your cash 7β20 days after the day that earned it.GET /api/v1/accountβwallets[].next_release_tick(andnext_release_at, real time) says when. - Reserve: a statement keeps back a reserve for the refunds still to come: the account's refund rate on the market over the last 91 days (refunds / gross sales) Γ the gross sales of the last 14 days. It is released by the next statements as it falls.
- Negative balance: if a statement's entries plus the reserve and carry are negative, the deficit is carried to the
next statement; if that one is negative too, it is charged to your cash (
negative_balance_charge; your cash may go negative, and then orders and payouts wait until it is positive again). - On demand: once per marketplace day and market you may ask for a disbursement (
POST /api/v1/disbursements, or the console): it releases everything posted before the start of the day seven days ago (the same 7-day hold, counted back from today), and the reserve too when you have no lot on that market any more; refused (400) when nothing would be paid, 409 when it was used today (marketplace day) or when a raised hold leaves its cutoff where the last release ended.wallets[].eligible_nowandon_demand_availablesay what it would pay. A raised hold never releases a day twice: a wallet's next statement is the first whose cutoff passes the last one released.
Every statement lists its entries by kind with the opening reserve and carry, the net, the new reserve and carry, and
what was disbursed or charged (GET /api/v1/statements: from_tick, to_tick = its cutoff, close_tick). The
transfer appears in both wallets of the ledger (disbursement), so cash + seller balance is always the account's whole
money.
Removals and maximum age
You may have units removed (shipped back to you: they become owned goods in your inventory, at the lot's unit
cost; on a competition account they are gone like a disposal) or disposed of, at the fees above: POST /api/v1/removals {market, msku, qty, kind: removal|disposal,
position_id?} (the oldest units first, or the named lot). Only units on hand can be ordered out: a request
for more units than are on hand and not already in your pending requests is refused (400, with the number you can
order out), and so is one naming a lot that has not arrived yet (400; request it again once it is on hand). A
removal is carried out within the marketplace hour β at the close of the hour it was requested in
(effective_tick) β on the units on hand; if fewer are left by then (units sold in the meantime), the rest of the
request stays open for the following hours. A request may be refused (400) while the market is catching up on its
closes (try again in a moment); a request can be cancelled while nothing of it has been worked (409 once a close
worked it). On an account without an account holder a removal is a disposal. Its fee accrues on the lot and is
posted at the day close.
Stock has no horizon, but a safety maximum age: units still on hand 546 days (78 weeks) after their lot
arrived are removed automatically to the account holder's owned goods (disposed of on an account without a holder),
at the removal fee (auto_removal_at_tick). Competition accounts write their lots off 112 days after the fill,
without a fee, so a competition can end.
Fulfilment-network capacity
An account may hold at most max(400, 6 Γ the cu ft it shipped over the last 91 days) cubic feet per market: on hand
+ inbound + every order of the account not yet filled (unpaid or paid) + the new line. A line beyond it is refused
(400) with the numbers, when it is ordered and again when it is paid; GET /api/v1/account β fulfilment reports
capacity_cuft, used_cuft, inbound_cuft and ordered_cuft per market.
Fee amendments
The fee card changes only forward, by amendments the operator schedules with at least 30 days' notice in
real time: an amendment names the real time it takes effect from and applies from the first marketplace day that
starts then (midnight, marketplace time: a day's storage and surcharges are charged under one schedule); it is published in rules.pending_amendments ({version, effective_tick, effective_at,
effective_sim_at, digest, note}) as soon as it is scheduled. From that day on every fee of every account is charged
under the new schedule (rules.fees.schedule_version, and each offer's fee_schedule); nothing already posted or
accrued changes, and the market itself (its demand, prices and the desk's record) never moves with the fees.
Public observations and your private record
The public API exposes information a seller can observe: current distributor quotes and availability, product identifiers and physicals, the fee card, inbound quotes and delivery windows, Buy Box price history, delayed BSR, rank drops and seller counts. Rank drops are a proxy for activity, not an exact unit-sales counter. No future supply, demand path, exact market sales, seller inventory or repricing behavior is exposed. Public execution statistics and sales-derived deal projections are unavailable on this marketplace.
Your authenticated positions, stock, ledger, statements and trade record show your own transactions and outcomes.
The daily record has step_hours: 24. Public listing signals accept resolution=hour|day|week (day by default,
up to 400 marketplace days per call). An arrival window is a quote, not disclosure of the lot's exact arrival before
receipt.
Determinism
The background catalogue, distributor batches and benchmark marketplace conditions are deterministic for a market and hour. Actual distributor availability also reflects buyers' reservations and purchases. Stocked participant offers compete on the sell side: current observable seller counts and the Buy Box include eligible received stock at the prices in effect. Historical public observations retain the aggregate prices and seller counts as observed, without disclosing the sellers' identities, quantities or sales.
What happens to your stock is deterministic given the market and what the accounts did: every draw (lead times, inbound issues, your share of the buy box, returns) comes from a stream keyed by the account, the SKU, the lot and the hour, so re-running an hour β or catching up on a day of hours after a restart β gives the same result, ledger entry for ledger entry.
Renamed fields and the API version
The API stays /api/v1; a client recognises the continuous marketplace by time_model: "continuous" in
GET /api/v1/markets/{id} (and in rules). What changes for a client written for the classic markets, where a tick is the period of one menu:
| was | on the continuous marketplace |
|---|---|
four market ids m15, m45, h2, h10 |
one market us; the old ids are accepted as aliases in paths and parameters, answers say us |
| a tick = the period of one menu | a tick = one marketplace hour: ticks_per_day 24, time_scale, tick_sim_at, sim_now; sim_at on the menu, history and tape rows, orders and the record |
| one menu per tick | offers open for days: valid_until, hours_left, sim_valid_until |
| an order fills at the close of its tick | expires_tick (payment window), paid_tick; fills at the close of the paid hour |
storage_per_session |
storage_per_day, storage_per_month; rules storage_per_cuft_day, storage_per_unit_day |
| lead times in ticks | in days: lead_time.unit / lead_unit = "days", arrives_window_days, lead_time_days |
sales_by_tick, buy_box_by_tick, price_by_tick, nsellers_by_tick, revealed_ticks |
sales_by_day, buy_box_by_day, price_by_day, revealed_entries, with step_hours 24; public seller-count history is at the listing signals endpoint |
settlement_horizon_ticks only |
also settlement_horizon_days, path_step_hours |
signal rows' rank_drops_prev |
rank_drops_step (the rank drops over the row's hours); rows by day with to_tick, ticks |
| tape and signals per tick | a resolution parameter: hour, day (the default) or week; answers add resolution, step_ticks; public execution statistics are unavailable (403) |
| rule periods in ticks | max_age_days, competition_writeoff_days, settlement_period_days, funds_hold_days, capacity_window_days, guardrail_window_days, days_of_supply_windows_days, publication_delay_hours, drops_window_days, drops_window_long_days |
| money posted at every close | posted once per lot and kind at each day close; accrued_today on lots until then; invoices (by marketplace month) on the stock view |
| on demand once per tick | once per marketplace day |
| amendments from a tick | effective_tick is the first marketplace hour of a day; effective_sim_at |
Configuration
XGM_TIME_SCALE (default 24; a divisor of 3600) sets the clock. XGM_AMAZON_CONFIG=/path/to/amazon.json overrides any
field of the engine's configuration (lists stand for tuples): every market field of the wholesale configuration
(categories, catalogue, demand, sellers, buy box, rank, supply, the desk β these generate the calibrated weekly
series the hourly market is drawn from), the fee schedule, physicals and returns of the weekly fields below, and the
marketplace's own, in marketplace days and hours:
| group | knobs |
|---|---|
| clock | time_scale (must equal XGM_TIME_SCALE), sim_epoch (the marketplace date and time of tick 0, a whole hour), hours_per_tick (1) |
| the market hour by hour | hour_profile (24 values), weekday_profile (7, Monday first), change_hour_span, rank_delay_hours, rank_scatter_blend_hours, drops_window_days, drops_window_long_days |
| supplier offers | offer_life_days, offers_alive, deal_share, supplier_processing_days, supplier_spread_hours |
| the desk | desk_horizon_days, desk_coverage_days, desk_period_days, desk_threshold_continuous, desk_explore_prob |
| stock and pricing | max_age_days, competition_horizon_days, dos_short_days, dos_long_days, utilization_window_days, guardrail_window_days, guardrail_factor, default_max_vs_list, capital_holding_rate (per week) |
| returns | returns (per category: the share of units returned and the share of returns sellable again; a list of [code, rate, sellable] replaces, a dict {code: [rate, sellable]} merges), refund_lag_days, return_back_lag_days |
| fee schedule | fees: a partial schedule β a dict keyed by category code, size tier or route code merges into the default table entry by entry, a list replaces the table (the fields are listed in rules.fees.schedule); the windows and periods it counts in weeks (rules.fees.schedule_week_fields) are read as weeks of seven marketplace days |
| physicals | physicals_from_titles, large_bulky_share, unit_weight_lb, density_lb_cuft, content_density_lb_cuft, content_factor, content_tare_lb, multipack_slack, multipack_tare_lb, bundle_slack, bundle_tare_lb, bundle_pad_in, carton_max_cuft, carton_max_lb |
For example:
{
"fees": {"referral": {"GRO": {"tiers": [[15.0, 0.08], [null, 0.15]], "min_fee": 0.0}},
"storage_standard": [0.78, 2.40],
"routes": {"parcel": {"per_lb": 0.45}}},
"returns": {"PET": [0.05, 0.6]},
"max_age_days": 364,
"refund_lag_days": [3, 14],
"guardrail_factor": 1.6
}
The configuration β the clock included β is part of the market's frozen identity: changing it, or XGM_TIME_SCALE,
needs a fresh XGM_DB_PATH β to change the fees of a running market, schedule an amendment instead (xgames amazon
fees amend, see Deploying). A fresh database records the market's history back to XGM_HISTORY_DAYS
(real days) before now; at time scale 24 that is 24 marketplace days per real day, and a history of more than 20,000
marketplace hours is refused at start unless XGM_ALLOW_LONG_BACKFILL=1. xgames amazon report and xgames amazon
calibrate print what a configuration produces and how its public series, aggregated to weeks, compare with a real
marketplace's.
API
All paths in the table below are relative to /api/v1. The API reference
includes a quantity-valid workflow, reservation semantics and errors. Public distributor/listing reads need no key;
account records need authentication.
The supported wholesale seller API includes (GET /api/v1/stock per SKU and lot, positions with stage, the
signals of a listing). The seller's endpoints β reads with your key, writes with the same access as placing orders
(an agent with trade access, or a competition account):
| Method & path | Description |
|---|---|
GET /markets/us/distributors |
aggregate buy-side catalogue, including 0 available units: {market, tick, sim_at, listings[] {cluster, sku, asin, title, available_units, supplier_count, best_unit_cost, minimum_order, order_increment, offers[], marketplace {buy_box, nsellers, sales_rank, rank_as_of, β¦}}}; an offer includes distributor identity, remaining units, minimum, increment and expiry; best-quote fields are null when none is orderable |
GET /markets/us/families/{cluster}/signals?resolution=day |
public Buy Box, delayed BSR, rank drops and seller count over time; no unit-sales series |
GET /markets/us/deals/{key}/inbound?qty= |
every route's inbound quote for a valid distributor quantity (default: largest valid quantity available): {market, offer_key, tick, qty, max_qty, available_units, minimum_order, order_increment, unit_cost, default_route, quotes[] {route, label, available, reason, cartons, identical_cartons, pallets, placement, carrier, placement_fee, prep, per_unit, total, lead, lead_typical, lead_min, lead_max, lead_unit, defect_fee, defect_risk, default}}, lead times in days (404 when the offer is not open now; 400 when quantity violates the current terms) |
POST /orders, POST /cart/items {β¦, route?, pricing?} |
an order or a cart line with its inbound route (default parcel) and a starting pricing rule; the order answers with expires_tick and closes_at |
PUT /pricing/{market}/{msku} {kind, offset?, offset_pct?, price?, min_price, max_price?, note?} |
set the rule: {market, msku, sku, rule, effective_from_tick, effective_from_at, preview {price_at_current_buy_box, active, reason, default_min, default_max, buy_box, β¦}}; 400 with the reason when the rule is invalid; 403 for a min_price under break-even (default_min) unless autonomous funding is on; set again in the same hour, it replaces the pending rule |
DELETE /pricing/{market}/{msku} |
back to the default repricer from the next marketplace hour |
GET /pricing?market=, GET /pricing/{market}/{msku} |
your rules; one rule with its history |
POST /removals {market, msku, qty, kind, position_id?} |
request a removal or disposal of on-hand units (201); 400 for more units than are on hand and not already in pending requests, or for a named lot not arrived yet; a disposal is 403 unless autonomous funding is on (the account holder disposes on the console) |
GET /removals?status=&market=, DELETE /removals/{id} |
your removal requests; cancel one still requested (409 once any of it is done) |
GET /stock |
your stock per SKU and lot (accrued_today, lead_time_days, arrives_window_days, today, days_of_supply) and the monthly invoices |
GET /statements?market=&limit=, GET /statements/{id} |
settlement statements, one with its entries |
POST /disbursements {market} |
disburse on demand: 201 with the statement and the new available_balance; 409 already used this marketplace day; 400 nothing to pay |
GET /ledger?wallet=&kind=&statement_id= |
your ledger by wallet (cash, us for the seller balance, or all); seller-balance entries carry the day's last tick and day N |
GET /account |
adds available_balance (cash), seller_balance, reserve, wallets[] (per market, with eligible_now, next_release_tick, next_release_at and on_demand_available) and fulfilment {market: {capacity_cuft, used_cuft, inbound_cuft, ordered_cuft}} |
Integration examples and validation
Use the developer quickstart, API reference and
Python client guide for the current wholesale contract. Select quotes from /distributors, calculate
valid quantities from their current minimum/increment/stock, request the route quote, then propose an order for
holder approval. Public sales-derived research endpoints are unavailable on v2.
The wholesale regression tests exercise finite shared supply, cart and order validation, inbound receipt, repricing,
shared sales competition, daily fees and statements, and the public/private data boundary against isolated local
databases. Legacy strategy scripts in client/smoke/ and client/examples/10_amazon_seller.py predate this contract;
they are not current v2 integration examples.
Operator note.
XGM_KERNEL=amazon_weeklyruns the earlier seller engine instead, with four markets of weekly sessions; it is kept for its record and its tests, and its documentation is served on such a deployment in place of this page. The fee schedule's fields named after its sessions (settlement_period_sessions,funds_hold_sessions,low_inventory_new_sessions,utilization_new_seller_sessions,capacity_window,reserve_window,refund_window,returns_window) count weeks of seven marketplace days here; the weekly-only fields (max_age_sessions,competition_horizon, the session windows) are not read by the continuous marketplace β set their day equivalents above.