Order Lifecycle

Every status a Magma order can move through, who acts at each step, and the terminal states. Includes a full state machine diagram.

An order is the agreement between a buyer and a seller for one channel. It walks through a sequence of statuses from the moment a buyer initiates a purchase to the moment the channel is fully open on chain.

This page is the reference for every MarketOrderStatus and MarketOrderPaymentStatus value. If you're building an integration that polls or reacts to order updates, this is the table you'll keep open.


State machine


MarketOrderStatus - full reference

The 17 in-flight and terminal statuses. The "Who acts" column tells you which party is expected to do something next; if the answer is "nobody", the order has stalled or completed.

StatusWho actsNext statesWhat it means
WAITING_FOR_SELLER_APPROVALSellerWAITING_FOR_BUYER_PAYMENT, SELLER_REJECTED, SELLER_FAILED_TO_REACTOrder created. Seller must accept (with a HODL invoice) or reject.
WAITING_FOR_BUYER_PAYMENTBuyerWAITING_FOR_CHANNEL_OPEN, BUYER_FAILED_TO_PAY, BUYER_REJECTEDSeller accepted. Buyer must pay the BOLT11 HODL invoice within its expiry.
WAITING_FOR_CHANNEL_OPENSellerSELLER_SENT_TRANSACTION, SELLER_FAILED_TO_OPEN_CHANNELPayment received and held. Seller must broadcast the channel funding tx.
SELLER_SENT_TRANSACTION- (chain)WAITING_FOR_ON_CHAIN_CONFIRMATION, SELLER_FAILED_TO_SEND_SWAPSeller submitted add_transaction. Funding TX is in the mempool.
WAITING_FOR_ON_CHAIN_CONFIRMATION- (chain)ON_CHAIN_CONFIRMATIONWaiting for confirmations on the funding TX.
ON_CHAIN_CONFIRMATION- (Magma)SELLER_OPENED_CHANNELTX confirmed. Magma verifying the channel exists in the graph.
SELLER_OPENED_CHANNEL- (Magma)VALID_CHANNEL_OPENING, INVALID_CHANNEL_OPENINGChannel detected. Magma checking that capacity, peer, and locks match the order.
VALID_CHANNEL_OPENING-CHANNEL_MONITORING_FINISHED✅ Channel confirmed valid. Buyer has the agreed inbound capacity.
CHANNEL_MONITORING_FINISHED-(terminal)✅ Lock period (promises.locked_min_block_length) elapsed. Order fully complete.
SELLER_REJECTED-(terminal)❌ Seller rejected the order.
SELLER_FAILED_TO_REACT-(terminal)❌ Seller never accepted or rejected before timing out.
BUYER_FAILED_TO_PAY-(terminal)❌ HODL invoice expired without payment.
BUYER_REJECTED-(terminal)❌ Buyer cancelled before paying.
SELLER_FAILED_TO_OPEN_CHANNEL-(terminal)❌ Seller accepted, payment landed, but the channel was never broadcast.
SELLER_FAILED_TO_SEND_SWAP-(terminal)❌ Swap leg failed after the funding TX was sent.
INVALID_CHANNEL_OPENING-(terminal)❌ Channel was opened but didn't match the agreed terms (wrong capacity, wrong peer, etc.).
ADMIN_CLOSED-(terminal)❌ Manually closed by Amboss support. Rare.

Success vs in-flight. VALID_CHANNEL_OPENING is the first success state - at this point the buyer can already route over the channel. CHANNEL_MONITORING_FINISHED adds the guarantee that the seller honoured the lock duration.


MarketOrderPaymentStatus - full reference

Tracks the Lightning payment leg specifically. Independent of the channel-opening state machine above.

Payment statusMeaning
PENDING_PAYMENTInvoice issued, waiting for payment.
SUCCESSFUL_PAYMENT✅ Buyer paid the HODL invoice.
HODL_INVOICE_TIMEOUT❌ Invoice expired before payment.
SELLER_INVOICE_EXPIRED❌ Seller's invoice expired before payment landed.
PAYMENT_FAILED❌ Payment attempt failed at the wallet or routing layer.
PAYMENT_REJECTED_BY_DESTINATION❌ Seller's node rejected the HTLC.
INVALID_PAYMENT_SECRET❌ Preimage mismatch.

Detecting terminal states programmatically

If you're polling an order, you only need to stop when it reaches one of these statuses:

const TERMINAL_STATUSES = new Set([
  // Success
  "VALID_CHANNEL_OPENING",
  "CHANNEL_MONITORING_FINISHED",
  // Failures
  "SELLER_REJECTED",
  "SELLER_FAILED_TO_REACT",
  "BUYER_REJECTED",
  "BUYER_FAILED_TO_PAY",
  "SELLER_FAILED_TO_OPEN_CHANNEL",
  "SELLER_FAILED_TO_SEND_SWAP",
  "INVALID_CHANNEL_OPENING",
  "ADMIN_CLOSED",
]);

const SUCCESS_STATUSES = new Set([
  "VALID_CHANNEL_OPENING",
  "CHANNEL_MONITORING_FINISHED",
]);

function isTerminal(status: string) {
  return TERMINAL_STATUSES.has(status);
}

function isSuccess(status: string) {
  return SUCCESS_STATUSES.has(status);
}

Never hard-code the in-flight list. Statuses can be added or refined; the safe pattern is to enumerate terminal states (which only grow) and treat anything else as "still in flight".


Polling cadence by phase

The expected wait at each step is very different. Adapt your polling interval so you're not hammering the API while a 6-block confirmation runs.

PhaseTypical durationRecommended poll interval
WAITING_FOR_SELLER_APPROVALSeconds to minutes5–10 s
WAITING_FOR_BUYER_PAYMENTUntil buyer pays (max: HODL invoice expiry)5–10 s
WAITING_FOR_CHANNEL_OPENSeconds5–10 s
WAITING_FOR_ON_CHAIN_CONFIRMATIONOne or more blocks (~10 min each)30–60 s
ON_CHAIN_CONFIRMATIONSELLER_OPENED_CHANNELSeconds15–30 s

See Tracking Orders for a complete polling reference implementation.


Next steps