Migrate from the Legacy API

Move a Magma integration from the deprecated api.amboss.space endpoint to magma.amboss.tech/graphql. Operation-by-operation mapping for buyers and sellers.

The old Magma operations on https://api.amboss.space/graphql are deprecated. Everything Magma-related now lives on its own endpoint:

https://magma.amboss.tech/graphql

This page maps every legacy operation to its replacement so you don't have to guess.

The legacy seller accept path is no longer reliable. If you sell liquidity, migrate sellerAcceptOrder first.


What stays the same

  • Your API key. Keys minted at account.amboss.tech/settings/api-keys work on both endpoints. Same Authorization: Bearer header, no re-issuing needed.
  • Order IDs and offer IDs. Same UUIDs, same records. An order created on the legacy API can be finished on the new one.
  • Order statuses. The MarketOrderStatus enum has the same 17 values as the legacy OrderStatus, with the same names.

What changes shape

  • Operations are namespaced. Instead of a flat sellerAcceptOrder, you traverse market.order.seller.accept. Queries hang off market, user, and node.
  • Arguments moved into input objects. Legacy sellerAcceptOrder(id:, request:) becomes accept(input: { order_id, payment_request }).
  • Mutations return objects, not Boolean. Most return { success }, so you select a field instead of reading a bare boolean.
  • Lists are paginated. Anything returning a list takes page: { limit, offset } and returns { list, total, pagination }.
  • Sizes are strings. size on order creation is a String, not a Float.

Seller operations

LegacyNewNotes
sellerAcceptOrder(id, request)market.order.seller.accept(input)input: { order_id, payment_request }. Still a BOLT11 HODL invoice, still needs at least 48 hours of expiry. See Sell Liquidity.
sellerRejectOrder(id)market.order.seller.reject(input)input: { order_id }.
sellerAddTransaction(id, transaction)market.order.seller.add_transaction(input)input: { order_id, tx_id }. The field is named tx_id but the format is unchanged: TXID:OUTPUT_INDEX, for example 5e8a3f...c4f1:0. See Sell Liquidity.
createOffer(input)market.offer.create(input)pubkey and min_block_length are now required. offer_side and offer_type are gone. See Create Offers.
updateOffer(input)market.offer.update(input)offer is now offer_id, and total_size is optional.
toggleOffer(id)market.offer.toggle(input)input: { offer_id }.
getUserOffers / getUser.market.offersuser.market.offers.offers(page)Paginated.
getUser.market.orders(status)user.market.orders.sales(input, page)The legacy query mixed both sides of the book. sales is your seller orders, purchases is your buyer orders.
getUser.market.pending_seller_ordersuser.market.orders.sales(input: { action_needed: true }).totalClose, not identical. action_needed means WAITING_FOR_SELLER_APPROVAL, WAITING_FOR_CHANNEL_OPEN, and SELLER_SENT_TRANSACTION. The legacy count also included WAITING_FOR_ON_CHAIN_CONFIRMATION, where the seller has nothing left to do. Pass an explicit status list if you need the old set.
getOfferOrders(id) / getUser.market.offer_orders(id)user.market.offers.get_offer(offer_id).orders(page)Orders grouped under one of your offers.

Finding your own sales was the most common migration question, so here it is in full:

query MySales {
  user {
    market {
      orders {
        sales(input: { action_needed: true }, page: { limit: 25, offset: 0 }) {
          total
          list {
            id
            status
            amount { satoshi { sats } }
            destination { pubkey alias }
          }
        }
      }
    }
  }
}

Buyer operations

LegacyNewNotes
createOrder(input)market.order.create(input)offer is now offer_id, and size is a String. Returns the order, not a boolean.
cancelOrder(id, reason)market.order.cancel(input)input: { order_id, cancellation_reason }. See Errors.
getOrder(id)user.market.orders.get_order(order_id)Moved under user. Access rules are unchanged: you must be a side of the order. See Tracking Orders.
getUser.market.orders(status)user.market.orders.purchases(input, page)Buyer side of the split described above.
getUser.market.pending_buyer_ordersuser.market.orders.purchases(input: { action_needed: true }).totalClose, not identical. action_needed here means WAITING_FOR_BUYER_PAYMENT only. Pass an explicit status list if you need the old set.

There is also a new one-shot buy flow, liquidity.buy, which picks a matching offer for you and works without an account. See Buy Liquidity.


Marketplace and account operations

LegacyNewNotes
getOffers(...)market.offer.offers(page)Public, no credentials. Paginated.
getOffer(id)market.offer.get_offer(offer_id)Public.
getBitcoinTxInfo(txId)market.transaction.get_outputs(tx_id)Returns the outputs of a transaction, which is what you need to pick the channel output index.
getSignInfonode.identifier_infoThe signing challenge for linking a node.
addNewPubkeyToAccount(identifier, signature)account.node.connect(input)input: { identifier, signature }.
getUser (nodes, email, telegram)userRoot field, no get prefix.

Fields that did not move

Some fields on the legacy OrderType have no equivalent on MarketOrder. Here is where each one stands and what you can use instead.

Legacy fieldStatusWhat to use instead
payment_hashNot exposedIt is the payment hash of the BOLT11 invoice you supplied in accept, so you already have it. It is also the hash of payment.lightning.invoice, which you can decode.
updated_atNot exposedcreated_at is still there. For change detection, compare status and payment_status between polls.
is_automatedNot exposedNo replacement.
chat_enabledGoneThere is no order messaging on the new API at all.
cancellation_reasonWrite onlyYou pass it in market.order.cancel(input), but you cannot read it back off an order.
seller_close_side / buyer_close_sideNot exposedNo replacement today. See the note below.
fee_above_cap_secondsNot exposedNo replacement.
closed_blocks_before_minNot exposedblocks_until_can_be_closed covers the forward-looking version: how many blocks are left before you may close the channel.
locked_fee_rate / locked_base_feeExposed as amountsSee Fee fields changed meaning.
messagesGoneNo order messaging on the new API.
buyer_scoresNot exposedNo replacement.

seller_close_side and buyer_close_side are the only way to tell whether a channel was closed early by the buyer rather than by the seller, which matters for reviewing sales quality. If your integration depends on them, tell us at [email protected] so we can weigh adding them back.


Fee fields changed meaning

This one bites if you skim it, because the names look similar but the units are not.

LegacyNewUnit
amboss_fee_ratenot fees.ambossLegacy was a ppm rate. New fees.amboss is the Amboss fee amount in sats for that order. Different field, different unit.
fixed_feefees.fixedSame value. Your agreed base fee, in sats.
variable_feefees.variableSame value, in sats. Your agreed rate applied to the order size.
seller_invoice_amountfees.sellerWhat you get paid, in sats. See the caveat below.
buyer_invoice_amountfees.buyerWhat the buyer pays, in sats. See the caveat below.
locked_fee_ratenot exposedThe rate itself isn't exposed, only the sats it produced. For accounting, use the amounts.
locked_base_feefees.fixedSame value.

Every field under MarketOrderFees is a SatoshiValue, so it is an amount, never a rate. Select sats for the number and historical_usd if you want the USD value at the time of the order.

fees.seller and fees.buyer read the final settled amounts. They return 0 on an order that has not settled yet, where the legacy seller_invoice_amount fell back to a computed estimate. Do not treat a 0 as "this sale earned nothing", check status first.


Deprecation timeline

The Magma operations on the legacy endpoint are deprecated and will be removed. No date is set yet, and we will give notice here before anything is switched off, but plan for it going away rather than treating it as a supported option.

It is also no longer actively maintained, so bugs in it will not be fixed. The seller accept path has already been unreliable there. Migrate seller mutations first.


No replacement yet

These legacy operations have no equivalent on the new API. Tell us at [email protected] if your integration depends on one.

  • sendMagmaMessage(orderId, msg) - messaging a counterparty about an order.
  • setOrderCloseSide(orderId, closedBy) - declaring which side closed the channel.
  • getOfferRecommendations(channelSize) - server-side offer matching. Use market.offer.offers and filter yourself, or let liquidity.buy do the matching.
  • getUser.market.pubkey_reputations - per-pubkey reputation scores.

Next steps