Skip to main content
This page explains the trading rules behind preview_order, list_my_positions and list_my_ruby_ledger. Everything here applies to v21_lmsr topics — the live market. Legacy v2_share topics are readable but cannot be traded through the Open API.

The stake: chosen by the user, bounded by the topic

Each topic fixes its own trading rules when it is created — the range of stakes it accepts, how deep its market is, and which rules version it runs. Those rules never change afterwards; a later platform change only affects topics created after it. The part an agent needs is published on every topic card and detail as stake_rules: stake_rules is null on v2_share topics.
Ask the user for the amount. If they said how many coins to stake, pass exactly that as amount_coins. If they didn’t, ask — never pick, infer or round an amount for them. An amount outside the range is refused with STAKE_OUT_OF_RANGE, never adjusted.
A user places one order per topic. There are no fees — the whole stake buys units — and no adding to or switching a position later.

Prices and opening probabilities

Each option’s implied_price (0–1, summing to 1 across a topic) is its current price. A topic can open at initial probabilities set when it is published rather than at an even split, so read the price instead of assuming 1/n. Buying moves the price: the preview shows price_now, price_after and the average price paid (avg_price).

Payout and ruby boosts

If the option a position is on wins, the position pays rubies; the stake is not returned. The payout is:
units is the raw unit count the stake bought. The ruby multiplier is 1 unless a ruby boost is live at one of three moments — when the order is placed, when the topic settles, or (in the app) when the position is sold. A running boost appears on the topic as ruby_boost (multiplier, ends_at — ends_at is exclusive; null when there is no boost), and on the order preview as ruby_multiplier.
  • Placed during a boost — the order records that multiplier. A boost ending later never lowers it.
  • Settled during a boost — positions still held when the topic settles get the higher of their recorded multiplier and the one live at settlement.
  • Sold in the app during a boost — the sale uses the higher of the recorded multiplier and the one live at the moment of sale.
So every payout_if_correct_rubies figure is a guaranteed minimum (units × the order’s current multiplier), not the final amount: if the topic settles while a boost is live, the position pays more. Present it as “at least N rubies if correct”. The API does not project a future boost into it — a boost live today may be over by settlement. Where the payout shows up:

Selling happens in the app only

In the SeeSaw app, a user can sell a whole position back for rubies. The Open API has no sell tool or endpoint — an agent cannot sell on the user’s behalf. If the user asks to sell, point them to the app. What the API does show is the result. A position sold in the app appears in list_my_positions with:
  • sold: true and sold_rubies — what the sale paid;
  • won, payout_rubies and payout_if_correct_rubies always null, and refunded always false. A sold position does not take part in settlement and is not refunded, whatever the topic’s outcome — even if the option it was on wins;
  • settled still turning true once the topic settles, because it describes the topic.
Read the row in this order: sold > refunded > settled (won / payout_rubies) > open. Selling still counts as the topic’s one order, so preview_order on that topic answers ALREADY_STAKED. The sale itself is a ruby_trade_sell row in list_my_ruby_ledger; its created_at is the time of the sale.

Where rubies come from

rubies on get_my_profile is the ruby balance. It moves when:
  • a position on the winning option settles (ruby_settlement, boost included) — or is taken back after a takedown or a changed ruling (ruby_revocation);
  • the user sells a position in the app (ruby_trade_sell);
  • the user’s opinions are backed, or later backers follow them in a relay (sapphire_creator_fee, sapphire_back_relay) — or those paybacks are clawed back when an opinion is taken down (sapphire_opinion_takedown);
  • the old sapphire balance was converted (sapphire_conversion, once).
list_my_ruby_ledger lists every one of these movements.

Sapphires have been merged into rubies

Sapphires used to be a separate reward for opinions. They have been merged 1:1 into rubies, and opinions now pay rubies. The sapphire-named fields are still returned so existing integrations keep working, with the same values as their ruby replacements, and will be removed in contract 3.0.0: ruby_payback includes what an opinion paid as sapphires before the merge.