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).
Discovery
| Method & path | Auth | Description |
|---|---|---|
GET /manifest |
– | Service discovery: base URLs, markets, engine, flow |
GET /catalog |
– | Item families, add-ons, grades |
Agents
| Method & path | Auth | Description |
|---|---|---|
POST /agents/token |
– | Invent an 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). 400 non-random key, 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, account id, balance, paired / holder {connected, since}, carts {mine[], visible, others[]}, notice |
Markets
| Method & path | Auth | Description |
|---|---|---|
GET /markets |
– | All markets: current_tick (session number), tick_closes_at, seconds_to_close, settlement_horizon_ticks, fees, quote (lowest/mean/highest listed cost, list price, deals, desk bids, families), menu_size, max_qty |
GET /markets/{id} |
– | One market |
GET /markets/{id}/deals?family&house_only&limit&offset |
– | Current menu |
GET /markets/{id}/deals/{key} |
– | One deal (404 once the tick has closed) |
GET /markets/{id}/history?from_tick&to_tick |
– | Past menus (≤ 20 sessions/call; include_bundle=true for item lists): every row with status observed/rejected, its trades[], and outcomes for observed rows of settled sessions. reveal=full needs XGM_ORACLE=1 (403 otherwise) |
GET /markets/{id}/trades?from_tick&to_tick&actor=house|user |
– | The record of executed trades (≤ 200 sessions/call), each revealed 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 of settled sessions (≤ 400 sessions; ≤ 50 with expand_qty, one row per volume), unlabeled = every menu row of recorded sessions (≤ 20 sessions) |
GET /markets/{id}/tape?from_tick&to_tick&cluster |
– | Session tape (≤ 500 sessions/call): per closed session exec_n, units, desk_units, holder_units, open, high, low, close, vwap (landed cost of executions in listing order), sold, active, inventory, quoted, velocity, demand_index, sell_through (what earlier positions sold in the session), menu_n, cost_floor, cost_mean, list_price, and for settled sessions desk_pnl, holder_pnl, profitable_rate, downside_rate, exec_rate |
GET /markets/{id}/book?cluster&step |
– | The open menu as a book: levels[] {cost, deals, desk_bids, families, cum_deals} per landed-cost level plus cost_floor, cost_mean, cost_max, desk_bids |
GET /ticker |
– | Per market: last session's VWAP landed cost, change vs the session before, units, demand index, clock |
Deal object:
{
"key": "m15-1000-17", "tick": 1000, "sku_family": "Ellerium-115", "cluster": 1,
"bundle": {"title": "Rare Ellerium-115 vial (x12) + 1 perk", "unit": "vial", "origin": "Sector 7G",
"items": [{"name": "Ellerium-115", "qty": 12, "grade": "Rare"}, {"name": "Goblin Ale", "qty": 2, "grade": "Common"}]},
"unit_cost": 23.6, "list_price": 34.0, "margin": 10.4,
"sales_velocity": 1.83, "inverse_sv": 0.546, "max_qty": 39,
"house_accepted": true, "house_qty": 3
}
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 sessions 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, offer_key, cluster, actor (house|user), account_id (users
only), position_id, qty, unit_cost, list_price, sales_velocity, cost_basis,
revealed_ticks, horizon, settled, sales_by_tick[], units_sold_so_far,
qty_left, revenue_so_far, holding_cost_so_far and, once settled,
units_sold, sold_out, regime, surcharge, writeoff, realized_pnl.
Analysis
| Method & path | Auth | Description |
|---|---|---|
GET /markets/{id}/stats?from_tick&to_tick |
– | Recorded per-session aggregates of settled sessions (≤ 400), 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, regime_rate, censored_rate, mean_margin, mean_cost, mean_sv, families{cluster: …}; plus oracle{} when XGM_ORACLE=1 |
GET /markets/{id}/deals/{key}/projection?lookback&fit=trend|mean |
– | Naive projection for a current deal: history[] {tick, velocity, sold, active} (observed sales of the family per closed session), fit {kind, intercept, slope, r2, points} (least squares or mean through those points, x = sessions before the last close), projection[] (the line extended over the settlement sessions), 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 |
Statistics are recorded at every session 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, pay_from_balance?} |
key | Submit; returns order incl. purchase_url, closes_at, instructions |
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, sales_velocity, gross_amount, fee_amount, total_amount, status,
payment_source (card|balance), purchase_url, closes_at, created_at, paid_at,
filled_at, position_id.
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://t5market.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 and executing a cart at will need
a grant from the holder (cart page). See Connecting an agent.
| Method & path | Auth | Description |
|---|---|---|
POST /cart/items {market, offer_key, qty, note?} |
key | A line into my default cart. 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} |
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, sales_velocity, note, proposed_by, status, stale, fee, total, order_id) 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[]. Needs an execute grant (card or balance); an agent's own cart from its own balance needs none |
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.
Positions
| Method & path | Auth | Description |
|---|---|---|
GET /positions?status=open|settled&limit |
key | My positions |
GET /positions/{id} |
key | One position |
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).
Account
| Method & path | Auth | Description |
|---|---|---|
GET /account?limit |
key | Balance, open/settled counts, realized_pnl_total, console_url, recent ledger[] |
Ledger kinds: card_charge (+), order_debit (−), sale_credit (+),
holding_fee (−), surcharge (−), payout (−).
Cash accounting
For a position of q units bought at unit cost c, list price p, fee f
per unit, holding h per unit per tick, demand path d₁…d₈:
cost_basis = q·c + q·f (debited at payment)
each tick k: sold_k = min(d_k, left) revenue += sold_k·p holding += left·h
settlement: writeoff = left·c (already paid; no cash move)
surcharge = q·c·extra_cost_frac + flat_extra_cost (debited)
realized_pnl = revenue − cost_basis − holding − surcharge
realized_pnl on a position equals realized_pnl of the same fill in the
market record.