πŸ“¦ FTSeller Wholesale Market Log in Β· Register

API reference (v1)

Interactive versions: Swagger UI, ReDoc, raw openapi.json.

Base path /api/v1. Errors are {"detail": "..."} with 400 (bad request / order rejected), 401 (missing or bad token), 404 (unknown market, deal not on the current menu, not your order), 422 (schema validation).

The continuous marketplace. This deployment runs one market, us (the classic ids m15, m45, h2 and h10 are accepted as aliases in paths and parameters; answers say us), on a marketplace clock: a tick is one marketplace hour (ticks_per_day 24, time_scale marketplace seconds per real second), offers stay open for days, orders fill at the close of the hour they are paid in, and the record has one entry per marketplace day. Every from_tick / to_tick below is in marketplace hours; answers carry sim_at (the marketplace date) next to tick. The API version stays v1; a client tells this deployment by time_model: "continuous" in the market status. Every renamed field is listed on The marketplace.

Discovery

Method & path Auth Description
GET /manifest – Service discovery: base URLs, markets, engine, flow
GET /catalog – Item families, add-ons, grades

Agents

Built for agentic operation: agents register themselves following the auto-registration protocol (GET /agents/protocol as data). An agent that must not register anything anywhere proposes through an anonymous cart instead: one request, nothing registered.

Method & path Auth Description
GET /agents/protocol – The auto-registration protocol as data: recommendation, rules, numbered steps with request shapes
POST /agents/token – Invent a random 80-character key for an agent without a reliable random source: token, key_id, recall_phrase_suggestion (nothing stored)
POST /agents/register {token, name, recall_phrase, agent?, operator?, purpose?} – Register your own key (80 chars [A-Za-z0-9]; first 20 = key id) with a recall phrase and a self-description (agent {model, version, vendor, kind, instance}, operator {type: user/organisation/system, name, contact, reference}); returns key_id, account_id, cart {id, checkout_url}, keep (a note to store). any 80-char key is accepted (trade_enabled and cart.kind say what your cart does); 409 already registered
POST /agents/recall {key_id, recall_phrase?} – Was this key id registered here: known, name, recall_phrase (the one chosen at registration), connected_to_holder, carts_visible, optional phrase_matches
GET /agents/me key Key id, profile, trade_enabled, cart_note, account id, balance, paired / holder {connected, since}, carts {mine[] (with kind), visible, others[]}, notice

Every 80-character key is accepted. POST /agents/register answers with trade_enabled, cart_note and cart.kind (trade: paying funds orders; own: a purchase cart β€” paying buys the goods outright for the holder). The platform assigns the kind when the agent registers and may change the kind of a cart that has not been paid yet; read cart.kind. POST /agents/token invents a random key.

Markets

Method & path Auth Description
GET /markets – The market us: current_tick (the open marketplace hour), tick_sim_at and sim_now (marketplace date and time), time_model (continuous), ticks_per_day, time_scale, tick_closes_at, seconds_to_close (real time), settlement_horizon_ticks / settlement_horizon_days and path_step_hours (the record: 112 daily entries), quote (lowest/mean/highest listed cost; list_price = mean resale price of the open offers with price_low, price_high; deals, desk bids, families), menu_size (offers open now), max_qty, rules
GET /markets/{id} – The market (us, or a classic id as its alias)
GET /markets/{id}/deals?family&house_only&limit&offset – Every offer open now, viewed at the open hour (valid_until, hours_left, sim_valid_until; the answer's sim_at)
GET /markets/{id}/deals/{key} – One offer (404 once it is no longer open)
GET /markets/{id}/history?from_tick&to_tick – The offers that appeared in a range of hours (≀ 20 ticks/call; include_bundle=true for item lists), each viewed when it appeared: every row with status observed/rejected, its trades[], and outcomes for observed rows once settled. reveal=full needs XGM_ORACLE=1 (403 otherwise)
GET /markets/{id}/trades?from_tick&to_tick&actor=house|user – The record of trades executed in a range of hours (≀ 200 ticks/call), each revealed day by day as far as time allows
GET /markets/{id}/coverage – Recorded range, history-load progress, live start, trade count, frozen engine identity
GET /markets/{id}/dataset.csv?from_tick&to_tick&split=labeled|unlabeled&expand_qty – Research CSV frames: labeled = executed trades, settled (≀ 400 ticks; ≀ 50 with expand_qty, one row per volume), unlabeled = every offer that appeared in closed, recorded hours (≀ 20 ticks). Every row carries the listing's own list_price and unit_cost
GET /markets/{id}/tape?from_tick&to_tick&cluster&resolution – The tape by marketplace day (resolution=hour|day|week, default day; ≀ 120 marketplace days/call): rows tick (first hour), to_tick, ticks, sim_at, price_open, price_high, price_low, price_close (resale price; list_price = the close), exec_n, units, desk_units, holder_units, notional, open, high, low, close, vwap, sold, revenue, active, inventory, inventory_value, sell_through, menu_n, cost_floor, cost_mean, supply_units, supply_value, advancers, decliners; quoted, velocity and demand_index are null (no velocity is quoted); the answer adds resolution, step_ticks
GET /markets/{id}/book?cluster&levels&window – Synthetic order book around the resale price, reconstructed from the last window rows of tape (this market has no limit order book): mid, spread, spread_method (roll, corwin_schultz, floor), tick, best_bid, best_ask, bids[] / asks[] {price, size, cum}, depth, imbalance, buy_volume, sell_volume, price_impact (Kyle's lambda), listed, listed_low, listed_high
GET /ticker – Resale price at the last close (last, price_basis), change vs the close before, cost (executed VWAP), units, notional turnover, clock
GET /pulse – The market pulse: totals (executions, units and turnover on record, units sold and results of settled lots, days on record, open interest), window (last 30 days: turnover, units, executions, per-day averages, best day), last_24h, days[] (per UTC day), markets[] (the same figures plus the last 48 marketplace days of tape) and recent[] (the latest settled trades with their result)

Deal object:

{
  "key": "us-2541-1", "tick": 2541, "sku_family": "Unique Pretzel, Sourdough Craft Beer Pretzel Rings, 11 Ounce", "cluster": 29,
  "bundle": {"title": "Unique Pretzel, Sourdough Craft Beer Pretzel Rings, 11 Ounce (Pack of 3)", "unit": "pack", "origin": "Mountain DC",
             "items": [{"name": "Unique Pretzel, Sourdough Craft Beer Pretzel Rings, 11 Ounce", "qty": 3, "grade": "New"}]},
  "unit_cost": 8.4779, "list_price": 21.1616, "margin": 12.6837, "max_qty": 120, "house_accepted": false, "house_qty": 2,
  "valid_until": 3027, "hours_left": 27, "sim_valid_until": "2026-05-07T03:00:00Z",
  "sales_rank": 380669, "sales_rank_avg": 326910, "rank_drops": 7, "rank_drops_long": 28, "rank_as_of": 2998, "nsellers": 12,
  "sku": "GRO-0029-G1", "asin": "B0UO2MXSVH", "msku": "B0UO2MXSVH-JZ2-000000", "fnsku": "X00ORXO0KF", "upc": "",
  "family": "Pudding Mixes multipack Β· GRO-0029", "listing_type": "multipack", "category": "Grocery & Gourmet Food",
  "category_code": "GRO", "category_size": 3000000, "category_listings": 40, "brand": "Unique Snacks", "pack": 3, "case_pack": 12,
  "size_tier": "large_standard", "unit_weight_lb": 2.54, "dimensions_in": [10.56, 6.33, 5.32], "cubic_feet": 0.2058,
  "shipping_weight_lb": 2.558, "units_per_carton": 4, "prep": {"label": true, "kit": true, "per_unit": 0.75},
  "referral_rate": 0.1498, "referral_fee": 3.17, "referral_min": 0.0, "fulfilment_fee": 6.68, "fulfilment_base": 6.45,
  "peak_surcharge": 0.0, "fuel_surcharge": 0.2258, "fba_fee": 6.68, "fees_at_price": 9.85,
  "storage_per_day": 0.005277, "storage_per_month": 0.160522,
  "peak_season": false, "fee_schedule": 0, "inbound_route": "parcel", "inbound_per_unit": 2.02,
  "inbound_routes": [{"route": "parcel", "label": "Partnered parcel", "available": true, "per_unit": 2.02, "lead_typical": 12, "lead_max": 35},
                     {"route": "express", "label": "Express (own carrier)", "available": true, "per_unit": 4.19, "lead_typical": 12, "lead_max": 35},
                     {"route": "ltl", "label": "Partnered LTL (pallets)", "available": true, "per_unit": 2.63, "lead_typical": 15, "lead_max": 42}],
  "lead_time": {"typical": 12, "min": 9, "max": 35, "unit": "days",
                "distribution": {"9": 0.0115, "10": 0.0537, "11": 0.1163, "12": 0.1581, "13": 0.1563, "14": 0.1234, "…": 0.0}},
  "return_threshold": 0.029, "net_margin": 0.8137
}

No sales velocity on this market: see The marketplace for every field (valid_until is the first hour the offer is no longer open; inbound_per_unit is the default route's fee for the offer's max_qty; inbound_routes[] and lead_time are in days β€” ask GET /markets/us/deals/{key}/inbound?qty= for your quantity).

History rows are deal objects (with title instead of bundle unless include_bundle=true) plus recorded, settled, status (observed = executed by the desk or an account holder, rejected = never executed, unrecorded = history not loaded yet) and trades[]. For observed rows of settled lots they also carry profit_curve[] (index qty-1: the realised profit at every volume the record can vouch for β€” null above the executed volume when the deal sold out, because demand beyond the stock on hand was never observed), known_up_to_qty, and house_profit / house_units_sold when the desk was among the executors. Rejected rows never carry outcomes, and no row carries demand: sales are observed, demand is not.

A trade object (trades[], /trades, /trades for your own): id, market, tick, sim_at, offer_key, cluster, actor (house|user), account_id (users only), position_id, qty, unit_cost, list_price, cost_basis, revealed_entries, settled, sales_by_day[], units_sold_so_far, qty_left, sku, arrived, lead_time, step_hours β€” one entry per marketplace day (step_hours 24; entry i covers the hours tick + 1 + 24i … tick + 24(i + 1)), lead_time in days once arrived. The desk's trades are held 112 days (horizon) and carry price_by_day[], nsellers_by_day[] and, once settled, units_sold, sold_out, realized_pnl. An account's lot is pooled and open_ended (horizon null): it reveals buy_box_by_day[] (never the account's own price), route, auto_removal_at_tick once arrived and, once settled, settled_tick, units_sold, sold_out, realized_pnl (and flows {kind: amount} on your own /trades only).

Analysis

Method & path Auth Description
GET /markets/{id}/stats?from_tick&to_tick&resolution – Recorded aggregates by marketplace day (resolution=hour|day|week, default day; ≀ 120 marketplace days/call), from executed trades: observed_n, observed_rate, house_n, house_rate, house_pnl, house_pnl_mean, house_roi, user_n, user_pnl, observed_profitable_rate, censored_rate, mean_margin, mean_cost, families{cluster: …}; rows carry tick, to_tick, ticks; plus oracle{} when XGM_ORACLE=1
GET /markets/{id}/families/{cluster}/signals?from_tick&to_tick&resolution – The listing's public signals by marketplace day (resolution=hour|day|week, default day) β€” rows[] {tick, to_tick, ticks, sim_at, sales_rank, rank_as_of, rank_drops_step, nsellers, sku, asin, buy_box} (rank and sellers as published at the row's last hour, the rank drops over its hours, the mean buy box), up to the open hour (≀ 400 marketplace days/call; default the last 120), whether or not a supplier offers the listing now. Deals, families, trades and both dataset frames carry sales_rank, sales_rank_avg, rank_drops, rank_drops_long, nsellers instead of a sales velocity (none is quoted anywhere: the tape's quoted and demand_index and the projection's quoted_velocity are null) β€” see The marketplace
GET /markets/{id}/deals/{key}/projection?lookback&fit=trend|mean – Naive projection for an open offer: history[] {day, tick, velocity, sold, active} (observed sales of the listing per closed marketplace day), fit {kind, intercept, slope, r2, points} (least squares or mean through those points, x = days before the last day close), projection[] (the line extended over the record's 112 days; params.step_hours 24), scenarios {low_mult, high_mult}, qty[], curve {low[], mid[], high[]} (cash P&L by volume under the projected path), best_qty, realised[] (settled similar deals: qty, pnl, pnl_repriced, sold_out, downside_event), samples {deals, settled, profitable, downside_events, sold_out, per_deal_velocity_p10/p50/p90}, params, quoted_velocity
GET /markets/{id}/projection?cluster&unit_cost&lookback&fit – Same for a hypothetical deal
GET /markets/{id}/families?window – Item families on the current menu with recorded outcome statistics
GET /trades?limit key My own executed trades

Owned goods, trade rounds, the exchange

Method & path Auth Description
GET /inventory key The account holder's owned goods: items[] (each with story, rarity, rarity_score, history{}, economy, source, provenance) and their open listings[]
GET /rounds?limit key My trade rounds: orders[], amount, fee_amount, charged, source, status (awaiting_payment, funded, expired, completed), transferred_units
GET /exchange/listings?currency=USD|GC&family&limit – Open listings on the exchange with their item; listing and buying are done on the web

Positions carry inventory {transferred_units, item_id, transferred_at} once settled; orders carry round_id.

Statistics are recorded at every marketplace hour's close (and for the whole loaded history), never recomputed.

Human-only helpers (no JSON): GET /markets/{id}/menu.csv (current menu as CSV) and GET /cart/template.csv.

Orders

Method & path Auth Description
POST /orders {market, offer_key, qty, route?, pricing?, pay_from_balance?} key Submit a real-money trade; returns order incl. purchase_url, closes_at, instructions. route: the inbound route (parcel by default, express, ltl; 400 when it is not available for the quantity); pricing: the SKU's starting pricing rule (applied from the hour after the fill when the SKU has none). The order must be paid before closes_at (real time; the start of marketplace hour expires_tick: one real hour, never after the offer ends) and fills at the close of the hour it is paid in (paid_tick); an account orders at most the offer's max_qty across its orders of it. 400 when the line would exceed the account's fulfilment-network capacity. 403 where trading is not open to the agent (a competition account trades its simulated balance). pay_from_balance needs the holder's autonomous funding switch for this agent (403 until then)
GET /orders?status&limit key My orders
GET /orders/{id} key One order

Order fields: id, market, tick, offer_key, deal_title, items[], qty, unit_cost, list_price, gross_amount, fee_amount, total_amount, status, payment_source (card|balance), purchase_url, closes_at, created_at, paid_at, filled_at, position_id, route, inbound, pricing, expires_tick, paid_tick (once paid), sim_at β€” fee_amount is the inbound fee, inbound the route's quote (lead times in days) and pricing the starting rule (when given).

Carts

Every account holder has a cart; every agent has one or more. An agent's carts are connected to the account holder who opens one of their checkout links (https://v2.ftseller.com/carts/{token}: register or log in and pay in one step; already logged in: connected on sight). Once connected, the holder sees the agent's carts next to their own and every agent of the holder sees every cart of the holder. Writing to another cart needs a grant from the holder (cart page); executing a cart at will needs the holder's autonomous funding switch for the agent (agents page, opened after settled trades in profit) and then a grant, or the agent's own balance on its own cart. See Connecting an agent.

Method & path Auth Description
POST /cart/items {market, offer_key, qty, note?, route?, pricing?} key A line into my default cart (with its inbound route and starting pricing rule, as on an order). Unconnected: status pending_pairing, checkout_url to hand over; connected: in_cart, other_carts
GET /cart key My default cart (items[] with pending_pairing / in_cart / ordered + order_id), its checkout_url, other_carts[]
DELETE /cart/items/{id} key Withdraw an un-ordered line
POST /cart/link key My default cart's checkout_url (and the older pairing_url, /link/{token})
GET /carts?since key Every cart I can see: id, name, owner {kind: agent/holder, agent_id, name}, mine, associated, checkout_url, open_items, stale_items, total, permissions {read, write, execute, execute_pay_with, execute_card_id, autonomous_funding, execute_note}
POST /carts {name} key Another cart of my own
GET /carts/{id} key One cart with items[] (id, market, tick, offer_key, deal_title, qty, max_qty, unit_cost, list_price, note, proposed_by, status, stale, fee, total, order_id, and route / pricing when set) and my permissions
POST /carts/{id}/items {market, offer_key, qty, note?} key, write Add a line to a cart I may write to (403 otherwise)
PUT /carts/{id}/items/{item} {qty} key, write Re-size (0 removes)
DELETE /carts/{id}/items/{item} key, write Remove an un-ordered line
POST /carts/{id}/checkout {pay_with?, item_ids?} key, execute Place and fund the cart's current lines: paid_with, total, skipped_stale, orders[]. 403 until the holder switched on autonomous funding for the agent; then an execute grant (card or balance), or the agent's own cart from its own balance
POST /carts/{id}/link key The cart's checkout_url

At checkout a line proposed by an agent is ordered on that agent's trading account, a line picked by the holder on the holder's Manual desk.

Anonymous carts

For agents that must not register anything anywhere. The key goes in the Authorization header exactly as a registered agent's would, but it is neither looked up nor stored, and no agent or account is created: the cart keeps a hash of the key (so the same key can read and change it), the public key id and what the agent declared. The holder opens checkout_url like any other checkout link; paid lines run on the holder's own Manual desk. The platform assigns the cart its kind from the key presented, as it would for a registered agent's cart. Any other key answers 404.

Method & path Auth Description
POST /anonymous/carts {items[] {market, offer_key, qty, note?}, name?, agent?, operator?, purpose?, summary?} key (presented, not registered) Open the whole proposal in one request: token, checkout_url, kind, kind_note, owner {kind: anonymous, name, key_id}, items[], open_items, total, status, follow[], endpoints, stored, instructions, keep. 400 if any line is not on a current menu (nothing is opened)
GET /anonymous/carts/{token} same key The cart: items[] with status (pending_pairing, in_cart, ordered, purchased), associated, status (waiting / in the holder's cart / paid), follow[] (order_id, order_status, position_id, position {status, ticks_done, horizon, units_sold, qty_left, pnl_so_far, realized_pnl} per paid line)
POST /anonymous/carts/{token}/items {market, offer_key, qty, note?} same key Add a line
PUT /anonymous/carts/{token}/items/{item} {qty} same key Re-size (0 removes); 409 once paid
DELETE /anonymous/carts/{token}/items/{item} same key Withdraw an unpaid line; 409 once paid

Positions

Method & path Auth Description
GET /positions?status=open|settled&limit key My positions
GET /positions/{id} key One position
GET /stock?market key My stock per SKU β€” rows[] {sku, msku, asin, title, cluster, qty_on_hand, qty_outstanding, cost_on_hand, cost_outstanding, units_sold, revenue, fees, holding_cost, cash_flows, flows, listing {on_listing, buy_box, nsellers, sales_rank, rank_as_of}, rule {now, default_repricer, changes_from_tick, …}, last_session {tick, price, buy_box, active, reason, rule_kind, shipped, …} (the last settled marketplace hour), today {day, tick, shipped, price, buy_box, active_hours, returned_units, rule_kind, reason} (the open marketplace day), days_of_supply {short, long, day} (30 / 90 days, as of the last closed day), oldest_on_hand_days, aged_band, returns_in_transit {to_refund, coming_back}, qty_awaiting_returns, removals_pending, next_auto_removal_tick, lots[] {position_id, qty, qty_left, stage, landed_cost, route, returns_pending, cash_flows, accrued_today, arrives_window and arrives_window_days (inbound), lead_time, lead_time_days, arrived_at_tick and age_days (arrived), auto_removal_at_tick}}, totals per market and invoices[] {account_id, market, month, days, from_tick, to_tick, by_kind, total} (the daily storage, aged-inventory and utilization postings by marketplace month) β€” see The marketplace

Position fields: id, order_id, market, opened_tick, settles_at_tick, deal_title, offer_key, qty, qty_left, ticks_done, horizon, unit_cost, list_price, cost_basis, revenue, units_sold, holding_cost, writeoff, surcharge, pnl_so_far, realized_pnl (null until settled), status, sales_by_tick[], created_at, settled_at, outcome {sold_out, downside_event, surcharge, writeoff} (settled only). A position is a lot: it also carries sku, stage, qty_outstanding, qty_on_hand, arrival_tick, lead_time, age_days, auto_removal_at_tick, cash_flows, flows {kind: amount}, accrued_today {kind: amount}, units {sold, restocked, removed, disposed, lost, returned}, returns_pending, last_sale_tick, price_by_tick[] β€” stage is inbound, on_hand, awaiting_returns or settled, lead_time (days) is shown once arrived, sales_by_tick and price_by_tick have one entry per marketplace day (price_by_tick is your own price, private), cash_flows and pnl_so_far = cash flows βˆ’ cost basis count the money posted at day closes, and accrued_today what the lot earned and paid since the last day close (it is posted at the next one); settles_at_tick is null (a lot settles at a day close once it is sold out, removed or disposed of and its returns are back). Trade-cart lines carry stock {sku, qty_on_hand, qty_outstanding} of the account they are ordered on.

Account

Method & path Auth Description
GET /account?limit key Balance, open/settled counts, realized_pnl_total, console_url, recent ledger[]

monthly_fee on the account answer says whether the account holder's participation fee for the current month is still due (it is collected with the first order-funding transaction of the month; see Payments).

GET /account also carries available_balance (the cash orders and payouts spend), seller_balance, reserve, wallets[] (per market: balance, reserve, carry, eligible_now, next_release_tick, next_release_at, on_demand_available) and fulfilment {market: {capacity_cuft, used_cuft, inbound_cuft, ordered_cuft}} (the fulfilment-network capacity in cubic feet). Ledger entries of a seller balance carry wallet (the market), tick (the last hour of the marketplace day that posted them; one entry per lot, kind and day, note "day N") and statement_id.

Ledger kinds β€” cash: card_charge (+), crypto_payment (+), order_debit (βˆ’), monthly_fee (βˆ’), payout (βˆ’), disbursement (+), negative_balance_charge (βˆ’); seller balance: sale_credit (+), referral_fee (βˆ’), fulfilment_fee (βˆ’), storage_fee (βˆ’), aged_inventory_surcharge (βˆ’), utilization_surcharge (βˆ’), low_inventory_fee (βˆ’), refund (βˆ’), referral_refund (+), refund_admin_fee (βˆ’), returns_processing_fee (βˆ’), removal_fee (βˆ’), disposal_fee (βˆ’), inbound_defect_fee (βˆ’), reimbursement (+), disbursement (βˆ’), negative_balance_charge (+) β€” see Payments.

Seller

The seller's own endpoints. Reads need your key; writes need the same access as placing orders (trade access, or a competition account). See The marketplace.

Method & path Auth Description
GET /markets/{id}/deals/{key}/inbound?qty= – Every route's inbound quote for qty units of a current deal (default and at most its max_qty): market, offer_key, tick, qty, max_qty, unit_cost, default_route, quotes[], each quote route, label, available, reason, qty, units_per_carton, 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 (placement: optimized or minimal; per_unit: the order fee per unit; lead times in days). 404 when the offer is not open now or the market has no inbound routes
PUT /pricing/{market}/{msku} {kind, offset?, offset_pct?, price?, min_price, max_price?, note?} key, trade Set the SKU's pricing rule (featured_offer, fixed, beat_lowest, default), effective from the next marketplace hour: market, msku, sku, rule, effective_from_tick, effective_from_at, preview {price_at_current_buy_box, active, reason, default_min, default_max}; 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} key, trade Back to the default repricer from the next marketplace hour
GET /pricing?market key My pricing rules
GET /pricing/{market}/{msku} key One SKU's rule and its history
POST /removals {market, msku, qty, kind, position_id?} key, trade Request a removal (to owned goods) or a disposal, worked at the close of the current marketplace hour on the units on hand: 201 with the request; 400 when qty is more than the units on hand not already in pending requests, when position_id names a lot that has not arrived yet, or while the market catches up on a close; a disposal is 403 unless autonomous funding is on (the account holder disposes on the console)
GET /removals?status&market key My removal requests (requested, partial, done, cancelled)
DELETE /removals/{id} key, trade Cancel a request still requested (409 once any of it is done)
GET /statements?market&limit key My settlement statements: kind, from_tick, to_tick, close_tick, opening_reserve, opening_carry, totals, net, reserve, carry, disbursed, charged (kind: scheduled or on_demand; totals: the released entries per ledger kind)
GET /statements/{id} key One statement with its ledger lines
POST /disbursements {market} key, trade Disburse on demand: 201 with the statement and the new available_balance; 409 when already used this marketplace day on that market; 400 when nothing would be paid or the market is catching up
GET /ledger?wallet&kind&statement_id&before_id&limit key My ledger by wallet (cash, a market id for its seller balance, or all), newest first, with wallet, tick and statement_id

Payments

Method & path Auth Description
GET /payments/methods – Which methods are available (balance, card via Stripe, crypto via Coinbase Commerce) and ready, the monthly participation fee, the payout terms and the terms/privacy URLs

Agents never handle money: the account holder pays on a cart's checkout_url (balance, card or crypto) or grants execute access. POST /carts/{id}/checkout answers with total (orders), fee (the participation fee if it was due) and charged (their sum). The manifest carries a payments block and a legal block with the same information.

Cash accounting

A lot of q units bought at unit cost c with an inbound fee f per unit:

cost_basis   = qΒ·c + qΒ·f                        (debited from cash at payment)
each hour from its arrival, accrued on the lot and posted to the seller balance at the day close (ref=position:{id}):
    sale_credit = soldΒ·price          referral_fee, fulfilment_fee per unit sold
    storage_fee, aged_inventory_surcharge, utilization_surcharge on the units on hand
    low_inventory_fee per unit shipped (when stock runs short)
    refund, referral_refund, refund_admin_fee, returns_processing_fee on customer returns
    removal_fee / disposal_fee, inbound_defect_fee
    reimbursement (+) of units lost inbound on a partnered route
cash_flows   = Ξ£ of those entries
realized_pnl = cash_flows βˆ’ cost_basis          (once sold out or removed and every return is back)

realized_pnl on a position equals realized_pnl of the same lot in the market record. The seller balance reaches cash only through settlement statements (disbursement); a lot's result does not depend on when its money is released.