Create Offers
Post liquidity for sale on the Magma marketplace - create, update, and toggle offers with conditions and onchain priority.
To sell liquidity on Magma you publish an offer: a listing that says how much capacity you'll provide, at what price, with what guarantees, and to which buyers. Once published, buyers can fill it through liquidity.buy or market.order.create.
This page covers creating and managing offers. For accepting and fulfilling the orders that land against them, see Sell Liquidity.
Selling requires an Amboss API key and at least one connected node. Connect your node first at account.amboss.tech/settings/nodes or programmatically via account.node.connect.
1. Create an offer
The market.offer.create mutation takes a CreateOfferInput and returns the new offer_id.
mutation CreateOffer($input: CreateOfferInput!) {
market {
offer {
create(input: $input) {
offer_id
}
}
}
}{
"input": {
"pubkey": "03abc...xyz",
"total_size": 10000000,
"min_size": 500000,
"max_size": 5000000,
"min_block_length": 4320,
"fee_rate": 500,
"base_fee": 1,
"fee_rate_cap": 1000,
"base_fee_cap": 100,
"onchain_priority": "MEDIUM",
"onchain_multiplier": 2,
"conditions": [
{
"condition": "NODE_CAPACITY",
"operator": "GREATER_THAN_OR_EQUAL_TO",
"value": "10000000"
}
]
}
}curl -X POST https://magma.amboss.tech/graphql \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $AMBOSS_API_KEY" \
-d '{
"query": "mutation($input: CreateOfferInput!) { market { offer { create(input: $input) { offer_id } } } }",
"variables": {
"input": {
"pubkey": "03abc...xyz",
"total_size": 10000000,
"min_size": 500000,
"max_size": 5000000,
"min_block_length": 4320,
"fee_rate": 500,
"base_fee": 1,
"fee_rate_cap": 1000,
"base_fee_cap": 100,
"onchain_priority": "MEDIUM",
"onchain_multiplier": 2
}
}
}'import { GraphQLClient, gql } from "graphql-request";
const magma = new GraphQLClient("https://magma.amboss.tech/graphql", {
headers: { Authorization: `Bearer ${process.env.AMBOSS_API_KEY}` },
});
const CREATE_OFFER = gql`
mutation CreateOffer($input: CreateOfferInput!) {
market { offer { create(input: $input) { offer_id } } }
}
`;
const { market } = await magma.request(CREATE_OFFER, {
input: {
pubkey: process.env.MY_NODE_PUBKEY,
total_size: 10_000_000,
min_size: 500_000,
max_size: 5_000_000,
min_block_length: 4320, // ~30 days
fee_rate: 500, // 500 ppm routing fee
base_fee: 1, // 1 sat base
fee_rate_cap: 1000,
base_fee_cap: 100,
onchain_priority: "MEDIUM",
onchain_multiplier: 2,
},
});
console.log("Offer ID:", market.offer.create.offer_id);CreateOfferInput fields
| Field | Required | Type | Description |
|---|---|---|---|
pubkey | ✅ | String | The pubkey of your connected node providing the liquidity. |
total_size | ✅ | Float | Total satoshis you're advertising on this offer. |
min_size | ❌ | Float | Minimum sats per order. Defaults to the marketplace minimum. |
max_size | ❌ | Float | Maximum sats per order. Defaults to total_size. |
min_block_length | ✅ | Float | Minimum blocks the channel must stay open. Common values: 4320 (30 days), 8640 (60 days), 12960 (90 days). |
fee_rate | ❌ | Float | Your routing fee rate, in ppm. |
base_fee | ❌ | Float | Your routing base fee, in sats. |
fee_rate_cap | ❌ | Float | Maximum ppm you promise not to exceed for min_block_length. |
base_fee_cap | ❌ | Float | Maximum base fee (sats) you promise not to exceed for min_block_length. |
onchain_priority | ❌ | OnchainPriority | LOW, MEDIUM, or HIGH. Selects the fee tier for the funding TX. |
onchain_multiplier | ❌ | Float | 1–5x multiplier on the funding TX fee. Higher = faster confirmation. |
conditions | ❌ | [OfferConditionsInput!] | Buyer eligibility rules (see below). |
Response
{
"data": {
"market": {
"offer": {
"create": {
"offer_id": "off_01HX9YQK7P8MVZ3FN4G2RWS6CD"
}
}
}
}
}2. Restrict buyers with conditions
conditions is an optional list. Every condition must pass for a buyer's node to qualify. Each entry is a (condition, operator, value) triple.
condition | Checks | Value type |
|---|---|---|
NODE_CAPACITY | Buyer's total capacity, in sats. | Integer string |
NODE_CHANNELS | Number of channels the buyer has. | Integer string |
NODE_SOCKETS | Buyer's socket strings. | Substring (use CONTAINS) |
PARALLEL_CHANNELS | Whether the buyer already has a channel with you. | "true" / "false" |
TERMINAL_WEB_RANK | Buyer's Amboss reputation rank. | Integer string |
Operators: EQUAL_TO, NOT_EQUAL_TO, GREATER_THAN, GREATER_THAN_OR_EQUAL_TO, LESS_THAN, LESS_THAN_OR_EQUAL_TO, CONTAINS, DOES_NOT_CONTAIN.
Example: "well-connected nodes with public sockets only"
[
{ "condition": "NODE_CAPACITY", "operator": "GREATER_THAN_OR_EQUAL_TO", "value": "1000000000" },
{ "condition": "NODE_CHANNELS", "operator": "GREATER_THAN_OR_EQUAL_TO", "value": "20" },
{ "condition": "NODE_SOCKETS", "operator": "CONTAINS", "value": "ipv4" }
]See Orders and Offers for the full schema.
3. Update an offer
market.offer.update accepts the same fields as create, except pubkey (an offer's node is immutable). Everything is optional - pass only what you're changing.
mutation UpdateOffer($input: UpdateOfferInput!) {
market {
offer {
update(input: $input) {
success
}
}
}
}{
"input": {
"offer_id": "off_01HX9YQK7P8MVZ3FN4G2RWS6CD",
"fee_rate": 750,
"max_size": 3000000
}
}const UPDATE_OFFER = gql`
mutation UpdateOffer($input: UpdateOfferInput!) {
market { offer { update(input: $input) { success } } }
}
`;
await magma.request(UPDATE_OFFER, {
input: {
offer_id: offerId,
fee_rate: 750,
max_size: 3_000_000,
},
});Updates only affect new orders. Already-accepted orders keep the fees, caps, and lock duration that were locked in at acceptance time (see promises on MarketOrder).
4. Toggle an offer on or off
market.offer.toggle flips an offer between ENABLED and DISABLED. A disabled offer rejects new orders but lets in-flight orders complete.
mutation ToggleOffer($input: ToggleOfferInput!) {
market {
offer {
toggle(input: $input) {
status
}
}
}
}{ "input": { "offer_id": "off_01HX9YQK7P8MVZ3FN4G2RWS6CD" } }{ "data": { "market": { "offer": { "toggle": { "status": "DISABLED" } } } } }status will be ENABLED, DISABLED, or ADMIN_DISABLED (the last one is a hard stop set by Amboss support - you can't toggle it back).
5. List your offers
query ListMyOffers {
user {
market {
offers {
offers(page: { limit: 20, offset: 0 }) {
list {
id
status
total_size
locked_size
filled_orders
created_at
}
total
}
}
}
}
}Onchain fee tier
onchain_priority and onchain_multiplier together control how much you'll spend on the funding TX when an order is accepted:
onchain_priority | Maps to |
|---|---|
LOW | Mempool low-priority tier (slowest, cheapest). |
MEDIUM | Default. |
HIGH | High-priority tier (fastest). |
The multiplier is a scalar applied on top, capped at 5x. Useful if you want to always confirm fast regardless of mempool state.
Funding TX fees are paid by the seller out of the channel's commitment. Setting these too high reduces your margin per order; too low risks WAITING_FOR_ON_CHAIN_CONFIRMATION stalling during congestion.