Trading — How it works
This app talks to the Open Bank Project (OBP) trading API. Everything below is a plain-English
guide for people new to trading, but every term maps directly to a real OBP endpoint. The asset
being traded has a code such as OGCR (a carbon-credit token), and it is priced in a
currency such as EUR.
The big picture: two separate systems
The trading screens are split into Offers and Market. These are two independent ways to trade — not two steps of one process. Each has its own matching engine inside OBP:
Offers
A simple, all-in-one order book. You post what you want to buy or sell, and OBP automatically matches your offer against other people's offers. Easiest place to start. You can list, filter and cancel your offers.
Market
A low-level toolkit where you drive each step by hand: place orders, match a buy with a sell, create the resulting trade, settle it, and move funds on-chain. More control, more steps. These endpoints can't be listed — you create things or look them up by ID.
Key point: an offer never becomes a market order. Offers are matched against other offers; market orders are matched against other orders. They are parallel subsystems, so pick one model and stick with it for a given trade.
Offers, in detail
An offer is a standing advertisement: "I will BUY 100 OGCR at 1 EUR each." When you post it, OBP tries to match it against existing offers in the order book. As it gets matched — fully or in part — each fill is recorded on the offer as an execution.
- offer_type
BUYorSELL— the direction you want to trade.- asset_code / asset_amount
- What you're trading (e.g.
OGCR) and how much. - price_currency / price_amount
- The price per unit of the asset and the currency it's quoted in.
- settlement_account_id
- The account that money and assets move through when the offer is filled.
- expiry_datetime (optional)
- When the offer should automatically lapse if not filled.
- minimum_fill (optional)
- The smallest amount you'll accept in a single match — avoids tiny partial fills.
- status
- Set by OBP:
active,filled,cancelledorexpired. - executions
- The fill history. Each execution records the amount, price, time and the
counterpart_offer_idit matched against.
Market, in detail
The Market endpoints model each stage of a trade's life as its own resource. The usual flow runs top to bottom:
1. Orders
A concrete instruction to buy or sell: a side (BUY/SELL), a price, a quantity and a settlement account. You create an order,
look it up, or cancel it (cancelling is idempotent — cancelling twice is still a success).
2. Matches
Pairs a buy order with a counter (sell) order, for a given amount and price. Creating a match automatically generates the corresponding trade.
3. Trades
The agreed deal that comes out of a match, linking a buy_order_id and a sell_order_id with the agreed amount and price. Look these up by ID.
4. Settlements
The follow-through that finalises a completed trade — moving the money and the asset. A
trade is the agreement; settlement is the delivery, and it can run in
steps until it's completed.
5. Withdrawals
Moves funds out of the system to a blockchain address. Tracked on-chain via a transaction hash and confirmation count.
Offers vs Market at a glance
| Offers | Market | |
|---|---|---|
| What it is | A standing, advertised intention | A step-by-step settlement toolkit |
| Matching | Automatic, against other offers | Manual — the marketplace operator pairs a buy and a sell order by their IDs |
| Can you list them? | Yes — filter by status / type | No — create or look up by ID |
| Best for | Getting started; everyday trading | Fine-grained control over each stage |
Why amounts are sent as strings
When creating offers and orders, amounts (asset_amount, price_amount, quantity, etc.) must be sent as JSON strings — e.g. "100.00", not 100. Sending a bare number returns OBP-10001: Incorrect json format.
This is deliberate. OBP stores money as an arbitrary-precision decimal (BigDecimal), and its JSON layer only accepts these values from strings — the code paths that would read
them from JSON numbers are disabled on purpose, with the note that converting from a JSON
number "may lose precision". Standard binary floating point can't represent values
like 0.1 exactly, which is unacceptable for money, so the string form is required
to preserve the exact value end to end.