Orders and Offers

The Magma marketplace data model - offers, orders, fees, conditions, and promises. The vocabulary you need for every API call.

Magma's API revolves around two entities: offers posted by sellers and orders that match a buyer to one of those offers. Once you understand the shape of each, every other operation falls into place.


Offer

An offer is a listing posted by a seller. It says: "I'll provide channels up to this size, with these fees and lock guarantees, to buyers who meet these conditions."

type MarketOffer {
  id: String!
  status: OfferStatus!          # ENABLED · DISABLED · ADMIN_DISABLED
  node: SimpleNode!             # The seller's node
  asset: ChannelAsset!          # BASE_ASSET (BTC) or TAPROOT_ASSET
  total_amount: SizeValue!      # Total liquidity advertised
  locked_amount: SizeValue!     # Liquidity reserved by in-flight orders
  min_amount: SizeValue!
  max_amount: SizeValue!
  fees: MarketOfferFees!        # amboss · fixed · variable
  promises: MarketOfferPromises! # base_fee_cap · fee_rate_cap · min_block_length
  conditions: [OfferConditions!] # Buyer eligibility (optional)
  onchain_priority: OnchainPriority # LOW · MEDIUM · HIGH (funding tx fee tier)
  onchain_multiplier: Float     # 1-5x multiplier on the funding tx fee
  filled_orders: Float!
  is_owner: Boolean!            # True if the caller created this offer
  created_at: String!
}

Offer status

StatusMeaning
ENABLEDOpen for new orders.
DISABLEDPaused by the seller. New orders blocked; existing in-flight orders unaffected.
ADMIN_DISABLEDDisabled by Amboss support. Same effect as DISABLED but the seller can't re-enable.

Available vs locked liquidity

total_amount is what was originally advertised. locked_amount is reserved by orders that haven't yet completed. The liquidity actually available for a new buyer is total_amount - locked_amount.


Order

An order is a buyer-seller match. It's created when a buyer calls liquidity.buy or market.order.create, and tracked through its full lifecycle by the MarketOrderStatus state machine.

type MarketOrder {
  id: String!
  status: MarketOrderStatus!       # See Order Lifecycle
  payment_status: MarketOrderPaymentStatus
  amount: SizeValue!               # The agreed channel size
  asset: ChannelAsset!
  source: Node!                    # Seller's node
  destination: Node!               # Buyer's node
  fees: MarketOrderFees!           # amboss · buyer · seller · fixed · variable
  promises: OrderPromises!         # Locked caps + min block length for this order
  payment: OrderPayment            # The HODL invoice
  options: LiquidityOptions        # is_private · is_rails_cluster · asset
  simple_offer: SimpleMarketOffer  # The offer that fulfilled this order
  transaction_id: String           # Funding TX once the seller broadcasts
  channel_id: String               # Short channel ID once confirmed
  confirmations: TxConfirmations
  blocks_until_can_be_closed: Int  # Counts down once the channel is open
  is_seller: Boolean!              # True if the caller is the seller side
  timeout: String                  # When the current state's deadline expires
  created_at: String!
}

See Order Lifecycle for the full status reference and Tracking Orders for the polling pattern.


Fees

Magma surfaces fees in two slightly different shapes - one on the offer, one on the order - because the order knows who's paying.

MarketOfferFees (on the offer)

FieldMeaning
fixedBase fee charged once per channel. In SatoshiValue.
variableRate-based fee, measured per million units of channel size (ppm).
ambossMarketplace fee taken by Amboss.

MarketOrderFees (on the order)

FieldMeaning
fixedSame as above, materialised for this order.
variableSame as above, materialised for this order.
ambossMarketplace fee for this order.
buyerTotal the buyer pays (fixed + variable + amboss).
sellerNet the seller earns.

Every fee field is a SatoshiValue with sats, btc, and usd (current rate) plus historical_usd (rate at order time).


Promises

The "promises" attached to an offer or order are the guarantees the seller is locking in for the duration of the channel:

FieldMeaning
min_block_length (offer) / locked_min_block_length (order)Minimum number of blocks the channel must stay open before the seller can close it. 4320 ≈ 30 days.
base_fee_cap / locked_base_fee_capThe seller commits not to raise their routing base fee above this number, in sats.
fee_rate_cap / locked_fee_rate_capThe seller commits not to raise their routing fee rate above this ppm.

For the buyer, these promises are what makes the inbound capacity actually usable for routing - without them, a seller could open the channel and immediately raise fees to make it unrouteable.


Offer conditions

Offers can restrict who's allowed to buy. Each OfferConditions entry is a (condition, operator, value) triple. All conditions must pass for the buyer's node to qualify.

input OfferConditionsInput {
  condition: OfferCondition!
  operator: OfferConditionOperator!
  value: String!
}

Conditions

conditionChecks
NODE_CAPACITYBuyer's total channel capacity, in sats.
NODE_CHANNELSNumber of channels the buyer's node has.
NODE_SOCKETSBuyer's socket strings (e.g. clearnet vs Tor). Use with CONTAINS.
PARALLEL_CHANNELSWhether the buyer already has a channel with this seller.
TERMINAL_WEB_RANKBuyer's Amboss reputation rank.

Operators

operatorSymbol
EQUAL_TO, NOT_EQUAL_TO=,
GREATER_THAN, GREATER_THAN_OR_EQUAL_TO>,
LESS_THAN, LESS_THAN_OR_EQUAL_TO<,
CONTAINS, DOES_NOT_CONTAINSubstring match - typically for NODE_SOCKETS.

Example

"Only sell to nodes with at least 10 BTC capacity and at least one Tor socket."

[
  { "condition": "NODE_CAPACITY",  "operator": "GREATER_THAN_OR_EQUAL_TO", "value": "1000000000" },
  { "condition": "NODE_SOCKETS",   "operator": "CONTAINS",                  "value": ".onion" }
]

See Create Offers for the full mutation reference.


Liquidity options

When buying, the options input lets you control the channel's properties:

input LiquidityOptionsInput {
  asset_id: String          # Channel asset (omit for BTC base asset)
  private: Boolean          # True = unannounced channel
  rails_cluster_only: Boolean # True = only accept from Rails cluster sellers
}
OptionEffect
privateChannel is unannounced; not visible in the public graph. Useful for routing-private wallets.
rails_cluster_onlyRestricts matching to Amboss Rails cluster sellers (higher reliability tier).
asset_idSelects a non-BTC asset. List available assets with the assets.list query.

Value types

Two scalar shapes appear everywhere:

type SatoshiValue {
  sats: String!             # Integer string, e.g. "500000"
  btc: String!              # Decimal string, e.g. "0.005"
  usd: String!              # USD at current rate
  historical_usd: String    # USD at the time of the resource's creation
}

type SizeValue {
  satoshi: SatoshiValue     # Populated for BTC channels
  asset: AssetAmount        # Populated for Taproot Asset channels
}

Amounts are strings. All numeric amounts (sats, total_size, usd_cents, …) are returned and accepted as decimal strings. Avoid round-tripping through JavaScript numbers - use a big-integer or decimal library.


Next steps