Boltz Docs
API: Boltz Backend
Search
K
Comment on page
🤖

REST API

This page lists all available endpoints of Boltz's RESTful HTTP API and shows how to use them.

Basics

Response and request encoding

All the responses to all calls are encoded as JSON objects. If endpoints require the client to provide any kind of arguments these also have to be encoded as JSON and sent in the body of a POST request. Make sure to set the Content-Type header of your POST requests to application/json if you are sending JSON encoded data in the body of the request.

Error handling

If a call fails for some reason the returned HTTP status code will indicate that, and an object will be returned that looks like this and gives the reason why the call failed:
{
"error": "message explaining why the call failed"
}

Backend Version

Returns the version of Boltz Backend serving the API. A good call to get started and see if Boltz API requests and responses are working.
URL
Response
GET /version
JSON object
Status Codes:
  • 200 OK
Response object:
  • version: the deployed version of Boltz Backend
Examples:
GET /version
{
"version":"3.2.1-7c38088"
}

Supported Pairs

In order to create a swap, one first has to know which pairs are supported and what kind of rates, limits and fees are applied when creating a new swap. The following call returns this information.
URL
Response
GET /getpairs
JSON object
Status Codes:
  • 200 OK
Response object:
  • info: contains information about special configuration parameters of the Boltz Backend deployment. As of writing this there is only one possible value:
    • prepay.minerfee: If the array contains this value, Boltz requires a small invoice for the miner fee to be paid before the actual hold invoice of a Reverse Swap is revealed. As of writing, Boltz does not require this prepayment and thus returns an empty array.
  • warnings: an array of strings that indicate that some feature of Boltz might me disabled or restricted. An example of a warning is:
    • reverse.swaps.disabled: Means that all reverse swaps (from Lightning to the chain) are disabled.
  • pairs: an object containing the supported pairs. The keys of the values are the IDs of the pairs (BTC/BTC is a special case with mainchain bitcoin as base asset and Lightning bitcoin as quote asset) and the values itself contain information about the pair:
    • hash: SHA256 hash of the JSON encoded data in the pair object.
    • rate: The exchange rate of the pair.
    • limits: a JSON Object containing the minimal and maximal amount of the pair's swap. The numbers are denominated 10 ** -8 of the quote asset.
      • maximalZeroConf: The maximal amounts that will be accepted without chain confirmations by Boltz.
    • fees: A JSON object that contains different kinds of fees:
      • percentage: The percentage of the "send amount" that is charged by Boltz as "Boltz Fee" for swaps from quote to base asset (e.g. Lightning -> Bitcoin).
      • percentageSwapIn: The percentage of the "send amount" that is charged by Boltz as "Boltz Fee" for a swap from base to quote asset (e.g. Bitcoin -> Lightning).
      • minerFees: The network fees charged for locking up and claiming funds on the chain. These values are absolute, denominated in 10 ** -8 of the quote asset.
Examples:
GET /getpairs
Response:
{
"info": [],
"warnings": [],
"pairs": {
"BTC/BTC": {
"hash": "05d0f522ef08dd66fa0f87f167cc1380eaf7e5227e698941ecb44876e0736cb8",
"rate": 1,
"limits": {
"maximal": 10000000,
"minimal": 50000,
"maximalZeroConf": {
"baseAsset": 0,
"quoteAsset": 0
}
},
"fees": {
"percentage": 0.5,
"percentageSwapIn": 0.1,
"minerFees": {
"baseAsset": {
"normal": 1360,
"reverse": {
"claim": 1104,
"lockup": 1224
}
},
"quoteAsset": {
"normal": 1360,
"reverse": {
"claim": 1104,
"lockup": 1224
}
}
}
}
},
"L-BTC/BTC": {
"hash": "769215ae0f8cb14d250374a77de530ac2887c927dc08f8efce74f3634df03171",
"rate": 1,
"limits": {
"maximal": 10000000,
"minimal": 10000,
"maximalZeroConf": {
"baseAsset": 0,
"quoteAsset": 0
}
},
"fees": {
"percentage": 0.25,
"percentageSwapIn": 0.1,
"minerFees": {
"baseAsset": {
"normal": 147,
"reverse": {
"claim": 152,
"lockup": 276
}
},
"quoteAsset": {
"normal": 1360,
"reverse": {
"claim": 1104,
"lockup": 1224
}
}
}
}
}
}
}

Creating Normal Submarine Swaps

This section walks you through creating Normal Submarine Swaps (Chain -> Lightning). They differ slightly depending on the kind of bitcoin that are swapped, more information below. Please note that Boltz works with 10 ** -8 decimals internally and all amounts in the API endpoints follow this denomination. All requests to create swaps have the following common values in the API request:
  • type: type of the swap to create. For Normal Submarine Swaps this is submarine .
  • pairId: the pair of which the swap should be created, for more check Supported Pairs
  • orderSide: currently we recommend using sell across all pairs of swap type submarine. The value buy for e.g. the L-BTC/BTC pair signifies a swap from mainchain Bitcoin to Liquid Lightning. As of writing, this is not supported and the backend will return "error": "L-BTC has no lightning support"
Normal Submarine Swaps: If you already know the amount to be swapped, you should also set invoice.
  • invoice: the invoice of the user that should be paid
If the amount is not known yet, a preimage hash has be specified. The invoice that is provided later during the lifecycle of the Submarine Swap has to have the same preimage hash as the one specified here.
  • preimageHash: hash of a preimage that will be used for the invoice that is set later on
We recommend verifing that pair data fetched previously is still accurate by additionally passing the pairHash argument in this call.
  • pairHash: hash string in the pair object of /getpairs
URL
Response
POST /createswap
JSON object
Status Codes:
  • 201 Created
  • 400 Bad Request: if the swap could not be created. Check the error string in the JSON object of the body of the response for more information
Response objects:
Response objects of all swaps have these value in common:
  • id: id of the newly created swap
  • timeoutBlockHeight: base asset block height at which the swap will expire and be cancelled
  • address: address in which the bitcoin will be locked up. For UTXO chains this is a SegWit P2SHP2WSH (P2WSH nested in a P2SH) for the sake of compatibility and for RSK it is the address of the contract that needs to be used
If a lightning invoice is set in this call, one will also find the following values in the response:
  • acceptZeroConf: whether Boltz will accept 0-conf for this swap
  • expectedAmount: the amount that Boltz expects to be locked on the chain

Normal Swaps: UTXO Chains

Normal Submarine Swaps from UTXO chains like Bitcoin work by deriving an address based on the preimage hash (of the invoice) and the refund public key of the user. Boltz then waits until the user sent bitcoin to the generated address.
Requests for these kind of swaps have to contain one additional parameter:
  • refundPublicKey: public key of a keypair that will allow the user to refund the locked up bitcoin once the time lock is expired. This keypair has to be generated and stored by the client integrating Boltz API.
Responses also contain one additional value:
  • redeemScript: redeem script from which the address is derived. The redeem script can (and should!) be used to verify that the Boltz didn't try to cheat by providing an address without HTLC
In case the address is for the Liquid Network, it will be blinded by a key that is also in the response:
  • blindingKey: hex encoded private key with which the address was blinded
If the invoice has been set, you will also get this value:
Examples:
POST /createswap
Request body:
{
"type": "submarine",
"pairId": "BTC/BTC",
"orderSide": "sell",
"refundPublicKey": "AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBGBkraVi05Eyn6slRQV5h+fX6rtpudOq0LqPEnbnbxRshMdhS56vKWawUNLkLZZ4hKsTdbJZvgTtO/rDc2WI/Gw",
"invoice": "lntb1m1pjv0dt5pp5y9dl3z50c5g6p26a86g432zdzvdlx6a565hk55a2ellz3t9f84jsdqqcqzzsxqyz5vqsp5a4k0f59u62na3fngv24nv5xjuxyf6qjnnj806se373h4gt9fmejq9qyyssqpeh42yy72pqzfwdfehvuru9s735vrgg324lxdp9gg8w6m379w8ajd3sxyy6f0qqfqa6vhk5k4pqfz6nys3u5xf68wcjyjygykn7za6cqf6flce"
}
Response:
{
"id": "E63LC4",
"bip21": "bitcoin:2NBBYeBZgY64nJKiibnGokwrBBPjoQeMzyx?amount=0.0010054&label=Send%20to%20BTC%20lightning",
"address": "2NBBYeBZgY64nJKiibnGokwrBBPjoQeMzyx",
"redeemScript": "a9148f8d01a3e1a794024fa78bd9c81d5ae9bb1c56d287632102bba4fbfe50ea8caf880cb367f7b0083c7e91c2bc2808c817823bd36385e3a376670319b125b17503aaaae268ac",
"acceptZeroConf": false,
"expectedAmount": 100540,
"timeoutBlockHeight": 2470169
}
Submarine Swap that includes the creation of a new channel:
POST /createswap
Request body:
{
"type": "submarine",
"pairId": "BTC/BTC",
"orderSide": "sell",
"refundPublicKey": "AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBGBkraVi05Eyn6slRQV5h+fX6rtpudOq0LqPEnbnbxRshMdhS56vKWawUNLkLZZ4hKsTdbJZvgTtO/rDc2WI/Gw",
"invoice": "lntb10m1pjv0w7jpp5upaf56avdlkjv9h602m9heaa004reuc36yjf2hwzcv3tk0kjaekqdqqcqzzsxqyz5vqsp5klkwplct9kuzp8whrmjvqxqjhnga907aa953xdeaqypa8mn6chtq9qyyssqlywerx9cdqxukf640kphw2rtz6uamtc0g94h7jt99jpspjxn653h6gn30a6ejndh4xuxuf2gxn2sndgqhvs33s5ayg70z4p4f7n267gp4tytl0",
"channel": {
"auto": true,
"private": false,
"inboundLiquidity": 30
}
}
Response:
{
"id": "e1Qtxa",
"bip21": "bitcoin:2Muq74He81w8Ts4n3zhPFd1JZbuWC62czux?amount=0.0100234&label=Send%20to%20BTC%20lightning",
"address": "2Muq74He81w8Ts4n3zhPFd1JZbuWC62czux",
"redeemScript": "a91479674970eaa348958799f6fc41ef379d00f9060f8763210385ad894cdd1f27f4c88ef403100420eed6cc006965a3a58e277cb05c6f469d6667031ab125b17503aaaae268ac",
"acceptZeroConf": false,
"expectedAmount": 1002340,
"timeoutBlockHeight": 2470170
}

Normal Swaps: EVM Chains

Currently Boltz only supports RSK Testnet
Swaps from account-based EVM chains like RSK do not require a new address for every swap. /createswap takes the details of the swap (like lightning invoice and pair) and Boltz waits until the user locked e.g. RBTC in the contract. The addresses of those contracts can be queried with /getcontracts and the address of the contract that needs to be used for the swap is also returned in the response of this request.
The request does not require any additional values.
But the response has one additional value:
  • claimAddress: which is e.g. the RSK address of Boltz. It is specified in thelock function of the swap contract
Examples:
POST /createswap
Request body:
{
"type": "submarine",
"pairId": "RBTC/BTC",
"orderSide": "buy",
"invoice": "lnbcrt1m1p0c26rvpp5hctw8zukj00tsxay5436y43qxc5gwvdc6k9zcxnce4zer7p5a4eqdqqcqzpgsp59mwcr4cj6wq68qj6pzyjtq2j89vnpumsejdmhw5uy4yukq3vd64s9qy9qsq2537ph4kt4xryq27g5juc27v2tkx9y90hpweyqluku9rt5zfexfj6n2fqcgy7g8xx72fklr6r7qul27jd0jzvssvrhxmwth7w4lrq7sqgyv0m7"
}
Response:
{
"id": "7PSEtx",
"address": "0xD104195e630A2E26D33c8B215710E940Ca041351",
"claimAddress": "0xe20fC13bad486fEB7F0C87Cad42bC74aAc319684",
"acceptZeroConf": false,
"expectedAmount": 1387707329,
"timeoutBlockHeight": 2006
}

Swap Rates

When sending chain bitcoin, before setting the invoice of a Normal Submarine Swap, you'll need to use this endpoint to figure out what the amount of the invoice you set should be. Send a POST request with a JSON encoded body with this value:
  • id: id of the Submarine Swap
URL
Response
POST /swaprates
JSON object
Status Codes:
  • 200 OK
  • 400 Bad Request: if the invoice amount could not be calculated. Check the error string in the JSON object of the body of the response for more information. A common case is where the user did not lock up chain bitcoin yet, which is a requirement in order to calculate an invoice amount: "error": "no coins were locked up yet"
Response object:
  • invoiceAmount: amount of the invoice that should be set with /setinvoice
Examples:
Request body:
{
"id": "BY8asG"
}
Response:
{
"invoiceAmount": 15713393
}

Setting an Invoice

In case the amount to be swapped is not known when creating a Normal Submarine Swap, the invoice can be set afterwards; even if the chain bitcoin were sent already. Please keep in mind that the invoice has to have the same preimage hash that was specified when creating the swap. Although the invoice can be changed after setting it initially, this endpoint will only work if Boltz did not try to pay the initial invoice yet. Requests to this endpoint have to be POST and should have the following values in its JSON encoded body:
  • id: id of the swap for which the invoice should be set
  • invoice: invoice of the user that should be paid
URL
Response
POST /setinvoice
JSON object
Status Codes:
  • 200 OK
  • 400 Bad Request: if the invoice could not be set. Check the error string in the JSON object of the body of the response for more information
Response objects:
What is returned when the invoice is set depends on the status of the Submarine Swap. If no funds were sent (status swap.created) the endpoint will return a JSON object with these values:
  • acceptZeroConf: whether Boltz will accept 0-conf for this swap
  • expectedAmount: the amount that Boltz expects you to lock in the chain HTLC
  • bip21: a BIP21 payment request for the expectedAmount of bitcoin and the address (only set when swapping from UTXO chains)
If chain bitcoin were sent already (status transaction.mempool or transaction.confirmed) the endpoint will return an empty JSON object, signifying success.
In case this endpoint is called again after an invoice was set and Boltz tried to pay it already:
  • error: error message explaining that Boltz tried to pay the invoice already and that it cannot be changed anymore
  • invoice: the invoice that was set and that will be used for the swap
Examples:
If no bitcoin were sent yet:
POST /setinvoice
Request body:
{
"id": "UwHIPg",
"invoice": "lnbcrt1m1p08epqjpp5yvv222x7te9asyzuhmjym083lwqpp5vlem09ewfeufyrp6f76w2sdql2djkuepqw3hjqnz5gvsxzerywfjhxuccqzpgsp5u6kxgf9daf64ptvl2ht74m6duc2neywx3ecvwxs07vf7egw5dy5s9qy9qsqakms0e7ww46q9cq2fa2ymrcx6nucfknjalkm5w4ywvjpfxdp5ya82drvdvxhqzzt2ysysh5u7rellzjse37fng3vsqafuwwz3kv4ykcquy8k29"
}
Response:
{
"acceptZeroConf": true,
"expectedAmount": 1359564,
"bip21": "bitcoin:QNaGS7WM31xANXQCbmrhXfnxUjxiGFpFwM?amount=0.01359564&label=Submarine%20Swap%20to%20BTC"
}
If bitcoin were sent already:
POST /setinvoice
Request body:
{
"id": "UwHIPg",
"invoice": "lnbcrt1m1p08epqjpp5yvv222x7te9asyzuhmjym083lwqpp5vlem09ewfeufyrp6f76w2sdql2djkuepqw3hjqnz5gvsxzerywfjhxuccqzpgsp5u6kxgf9daf64ptvl2ht74m6duc2neywx3ecvwxs07vf7egw5dy5s9qy9qsqakms0e7ww46q9cq2fa2ymrcx6nucfknjalkm5w4ywvjpfxdp5ya82drvdvxhqzzt2ysysh5u7rellzjse37fng3vsqafuwwz3kv4ykcquy8k29"
}
Response:
{}
If the invoice was previously set and Boltz tried to pay it already:
POST /setinvoice
Request body:
{
"id": "UwHIPg",
"invoice": "lnbcrt100u1p0gv8hjpp5j0vs0te6wykahrp3aammm46m73n2afzk6a87ezfp3p58qpcpu4wqdqqcqzpgsp5j6wue634lac577xnupy8auvq7n9062vshvvc6xszq4jt5q9phhzq9qy9qsqhs7zrs98tu669xz7w0gqy96g5pvs9p6lssmyseg7a92kpjlzramk8khyzkd8x4nl2zasekmwt45z6pe78rk032lkmshjdnesw2vukwgqtglt89"
}
Response:
{
"error": "lightning payment in progress already",
"invoice": "lnbcrt1m1p08epqjpp5yvv222x7te9asyzuhmjym083lwqpp5vlem09ewfeufyrp6f76w2sdql2djkuepqw3hjqnz5gvsxzerywfjhxuccqzpgsp5u6kxgf9daf64ptvl2ht74m6duc2neywx3ecvwxs07vf7egw5dy5s9qy9qsqakms0e7ww46q9cq2fa2ymrcx6nucfknjalkm5w4ywvjpfxdp5ya82drvdvxhqzzt2ysysh5u7rellzjse37fng3vsqafuwwz3kv4ykcquy8k29"
}

Creating Reverse Submarine Swaps

This section walks you creating Reverse Submarine Swaps (Lightning -> Chain) and is similar to creating Normal Submarine Swaps. In the same way, requests and responses change slightly depending on the kind of bitcoin involved in the swap. Keep in mind, Boltz uses 10 ** -8 as denomination for responses on the API.
All requests bodies extend from:
  • type: type of the swap to create. For Reverse Submarine Swaps this is reversesubmarine.
  • pairId: the pair of which the swap should be created, for more check Supported Pairs
  • orderSide: currently we recommend using buy across all pairs of swap type reversesubmarine. The value sell for e.g. the L-BTC/BTC pair signifies a swap from mainchain Bitcoin to Lightning on Liquid. As of writing, this is not supported and the backend will return "error": "L-BTC has no lightning support"
  • preimageHash: the SHA256 hash of a preimage that was generated by the client. The size of that preimage has to be 32 bytes or claiming will fail
There are two ways to set the amount of a Reverse Swap. Either by specifying the amount of the invoice Boltz will generate:
  • invoiceAmount: amount of the invoice that will be generated by Boltz
Or by setting the amount that will be locked in the chain HTLC. That amount is not what you will actually receive because of transaction fees required to claim the HTLC. But those can be approximated easily in advance and when overestimating a little, a quick confirmation of the claim transaction can be ensured.
  • onchainAmount: amount Boltz will lock in the chain HTLC
We recommend verifing that pair data fetched previously is still accurate by additionally passing the pairHash argument in this call.
  • pairHash: hash string in the pair object of /getpairs
URL
Response
POST /createswap
JSON object
Status Codes:
  • 201 Created
  • 400 Bad Request: if the swap could not be created. Check the error string in the JSON object of the body of the response for more information
The JSON object in the response extends from:
  • id: id of the newly created swap
  • lockupAddress: address derived from the redeemScript or contract in which Boltz will lock up bitcoin
  • invoice: hold invoice that needs to be paid before Boltz locks up bitcoin
  • timeoutBlockHeight: block height at which the Reverse Swap will be cancelled
In case the invoice amount was specified, the amount that will be locked in the chain HTLC is also returned:
  • onchainAmount: amount of chain bitcoin that will be locked by Boltz
Boltz backend also supports a different protocol that requires an invoice for miner fees to be paid before the actual hold invoice of the Reverse Submarine Swap. If that protocol is enabled, the response object will also contain a minerFeeInvoice. Once the minerFeeInvoice is paid, Boltz will send the event minerfee.paid and when the actual hold invoice is paid, the chain bitcoin will be sent.

Reverse Swaps: UTXO Chains

The request has to contain one additional value:
  • claimPublicKey: public key of a keypair that will allow the user to claim the locked up bitcoin with the preimage. This keypair has to be generated and stored by the client integrating Boltz API.
And so has the response:
  • redeemScript: redeem script from which the lockup address was derived. The redeem script can (and should!) be used to verify that Boltz didn't try to cheat by creating an address without a HTLC
In case the lockup address is on the Liquid Network, it will be blinded by a key that is also in the response:
  • blindingKey: hex encoded private key with which the address was blinded
Examples:
POST /createswap
Request body:
{
"type": "reversesubmarine",
"pairId": "L-BTC/BTC",
"orderSide": "buy",
"invoiceAmount": 1000000,
"preimageHash": "51a05b15e66ecd12bf6b1b62a678e63add0185bc5f41d2cd013611f7a4b6703f",
"claimPublicKey": "03b76c1fe14bab50e52a026f35287fda75b9304bcf311ee85b4d32482400a436f5"
}
Response:
{
"id": "v3CfMa",
"invoice": "lntb10m1pjvsy8ppp52xs9k90xdmx390mtrd32v78x8twsrpdutaqa9ngpxcgl0f9kwqlsdpz2djkuepqw3hjqnpdgf2yxgrpv3j8yetnwvcqz95xqrrsssp5hzcjq972f9cl8c6u3zechepm65hjceaqvlzye6kc23qkz5rhva6q9qyyssq4kkw9fwjq7n9cm4j3ajj2a92ka0zyeg3sxppfy932c62pnsqkw7nhvg9rrxztszw37wqtal4cchw2f4s09qe48pngsl9euv7wjlz93qqrfx60s",
"blindingKey": "897034f717beb12a3c2b7ae8c08c5c4def7bc7cfb6efa3713c617f28d90d1419",
"redeemScript": "8201208763a914be1abd8e8d7ef7e64a9c6e1e2f498f3a92e078a2882103b76c1fe14bab50e52a026f35287fda75b9304bcf311ee85b4d32482400a436f5677503dbf40eb175210330fd4cfd53b5c20886415c1b67d2daa87bce2761b9be009e9d1f9eec4419ba5968ac",
"lockupAddress": "tlq1qqdd0v79wcqnpvujf5mfp88d5cz8rynk0awr6m84ca8pzn39kwagsh4z204s9d5sww3cxckd47wjxlqwl3u6tgdqfa877txqt9m8wgk22qwyp5yzxaf40",
"timeoutBlockHeight": 980187,
"onchainAmount": 995724
}
In case the prepay miner fee protocol is enabled:
Request body:
{
"type": "reversesubmarine",
"pairId": "BTC/BTC",
"orderSide": "buy",
"claimPublicKey": "0391fbaf549578fd7c2cb26b216441825bd780d85dba1f3d706e2f206587e96266",
"invoiceAmount": 100000,
"preimageHash": "2215034def003b63b2717fccd4ce8259f4807a39318c14e2bdd42639ca989a45"
}
Response body:
{
"id": "mVSKyF",
"invoice": "lnbcrt996940n1p0dhjr3pp5yg2sxn00qqak8vn30lxdfn5zt86gq73exxxpfc4a6snrnj5cnfzsdql2djkuepqw3hjqsj5gvsxzerywfjhxuccqzy0sp5hjcvwl2glrq9n3vzm8072cdruz3hhz70edml8g0u76gryve6np4q9qy9qsqzw5w8ulxjgrg478hz4enjrw0a9tedl8s3n879xqh3mhn0pxrvajrz9qnnsr58twx4a30gk57d4fykm7x3v2vcamw7k4ny9fkpwl65vcpw8v5em",
"redeemScript": "8201208763a914fb75ff5dc4272c2da33d744615905f54b62de41588210391fbaf549578fd7c2cb26b216441825bd780d85dba1f3d706e2f206587e962666775028e01b1752102c22801bd7dd3a6afb780671c1c983fcd91fa46826eadd82e325e7e13bb348a9768ac",
"lockupAddress": "bcrt1qweryu6nk8gn5lj8ar5kjdy476wynheszg0lumu6jx83l2v6f435stlel03",
"onchainAmount": 98694,
"timeoutBlockHeight": 398,
"minerFeeInvoice": "lnbcrt3060n1p0dhjr3pp5sk2u4rt0z8rrl6jj62d6szqvsdejj8kjcxa8tdt4dau5rtyskj6qdp4f45kuetjypnx2efqvehhygznwashqgr5dusyy4zrypskgerjv4ehxcqzpgsp5qtsm5vfy9yq8kjpthla67jagmcxnj529pm3edk94npf6fekq2sxq9qy9qsqmun0z8ed4kp9dhp7lthvzdrx3ngmjs32smx6l4hvyyktv92mf348aftgrwf44sl94ewywr3sw8dc4acy63yamxxpjtd4pkkr2uw2h5gpqc3d3y"
}

Reverse Swaps: EVM Chains

Currently Boltz only supports RSK Testnet
Requests to create swaps for Reverse Submarine Swaps from account-based EVM chains like RSK have to contain one additional value:
  • claimAddress: address from which the bitcoin will be claimed
The response also has one more property:
  • refundAddress: the address of Boltz which is specified as refund address when it is locking up funds
Also, Boltz offers an optional protocol called EVM prepay miner fee that allows the user to pay an additional lightning invoice to pay for gas on the EVM chain to claim funds. In this process, Boltz sends some e.g. RBTC to the claimAddress in the lockup process in case the user's claimAddress does not have enough RBTC to pay gas to claim the funds. To use that protocol set the following property in the request body to true.
  • prepayMinerFee: if the prepay miner fee protocol should be used for the Reverse Swap
When the EVM prepay miner fee protocol is used the response will contain two more values. One is the amount of RBTC that will be sent to claimAddress in the lockup process. The other is an invoice for the RBTC sent. Only when both invoices are paid the chain bitcoin will get locked.
  • prepayMinerFeeAmount: amount of e.g. RBTC that will be sent to the claimAddress with the lockup transaction from Boltz
  • minerFeeInvoice: invoice that pays for the RBTC sent in the lockup process
Examples:
POST /createswap
Request body:
{
"type": "reversesubmarine",
"pairId": "RBTC/BTC",
"orderSide": "sell",
"claimAddress": "0x88532974EC20559608681A53F4Ac8C34dd5e2804",
"invoiceAmount": 100000,
"preimageHash": "295b93a766959d607861ab7b7a6bf9e178e7c69c3cc4ca715065dfe9d6eea351"
}
Response body:
{
"id": "1H6eCx",
"invoice": "lnbcrt1m1p0ega6epp599de8fmxjkwkq7rp4dah56leu9uw035u8nzv5u2svh07n4hw5dgsdpq2djkuepqw3hjq42ng32zqctyv3ex2umncqzphsp5gxshtrx3y0mt3llm3537qqy0ylf722hykv2zm777dwap9e60glfq9qy9qsqa93q725njkt9dupu9cddtchwcmyg7zsltrw8gcyzsc4tv74ss26y00z7tutrqks8wgh8s286ayy2tmrul0q0ysvxjzv793ylcdr553gqjhgny2",
"refundAddress": "0xe20fC13bad486fEB7F0C87Cad42bC74aAc319684",
"lockupAddress": "0xD104195e630A2E26D33c8B215710E940Ca041351",
"onchainAmount": 1210297576,
"timeoutBlockHeight": 2006
}

Swap Status

Before handling status events of this method it is recommended to read: Swap Types & States
To query the status of a swap one can use this endpoint which returns a JSON object containing the status of the swap. Possible states and status events are documented in the section Swap Types & States.
Requests querying the status of a swap have to be POST and contain a single value in its JSON encoded body:
  • id: the id of the swap of which the status should be queried
URL
Response
POST /swapstatus
JSON object
Status Codes:
  • 200 OK
  • 404 Not Found: if the swap with the provided id couldn't be found
  • 400 Bad Request: if the id argument wasn't provided
Response object:
  • status: status of the swap, e.g. transaction.mempool & transaction.claimed for successful Normal Submarine Swaps and transaction.mempool and transaction.confirmed for successful Reverse Submarine Swaps
  • transaction: for Reverse Submarine Swaps, this field contains lockup transaction details in the statestransaction.mempool and transaction.confirmed
    • id: id of the lockup transaction
    • hex: hex encoded lockup transaction (only set for transactions on UTXO chains)
    • eta: if the status is transaction.mempool, this value is the estimated time of arrival (ETA) in blocks of when the transaction will be confirmed. Only set for transactions on UTXO chains.
  • zeroConfRejected: set to true for Swaps with the status transaction.mempool and a lockup transaction that is not eligible for 0-conf
  • failureReason: set when it's necessary to further clarify the failure reason
Examples:
POST /swapstatus
Request body:
{
"id": "Asnj2Y"
}
Response:
{
"status": "invoice.paid"
}
POST /swapstatus
Request body:
{
"id": "ryUK9G"
}
Response:
{
"status": "transaction.mempool",
"transaction": {
"id": "31fcddf287d985eef85211b75976cd903dba3008a8e13b597e1b54941278c29f",
"hex": "01000000000101618cd5c50221577a1b98ae4a73f652917f9d2e343b9bc6a978239da78dfcbc630000000000ffffffff02b878010000000000220020ddc8dd3bcb45660e421fc3129bfdcb317446c27ce909369d4c8cb17bbd6d4951c718393b00000000160014ea9e0fc9432fc8b6831e94ac3974d46d1ba1c62f024830450221008b14ecce2eebb2ec7e56c53de4796603fbd22cfd269f3a5249446b79987dec36022059b68568a57ebfbd50cc792af3d514c507af20e795ff5f0bf2a02d2fc44be223012103a1ad2a3891018e856700a20a4dea6bea9f4bba58ab3ca7cbaefaa06e805770d100000000",
"eta": 2
}
}
POST /swapstatus
Request body:
{
"id": "gnIthU"
}
Response:
{
"status": "transaction.lockupFailed",
"failureReason": "locked 1396075383 is less than expected 1396075384"
}

Swap Status Stream

To avoid querying the /swapstatus endpoint regularly to get the latest swap status, this endpoint streams swap status updates via Server-Side Events.
Requests to this endpoint have to provide the required swap id parameter via an URL parameter because all requests have to be of the method GET.
Every event in the Server-Side stream has data that is encoded exactly like the JSON object of the /swapstatus endpoint. Please have a look at the examples below for a reference implementation in JavaScript of handling the stream.
URL
Response
GET /streamswapstatus
Server-Side event stream
Examples:
Server-Side event streams have to be handled differently from regular HTTP responses. Below is a sample implementation in JavaScript and also what a raw response of a Server-Side event stream looks like.
Sample implementation in JavaScript:
var stream = new EventSource(boltzApi + '/streamswapstatus?id=' + swapId);
source.onmessage = function(event) {
const data = JSON.parse(event.data);
console.log('Swap status update:' + data.status);
};
Raw response:
data: {"status":"transaction.mempool"}
data: {"status":"invoice.paid"}

Swap Timeouts

Boltz Swaps have different timeouts for each pair. This endpoint allows querying those timeouts denominated in blocks of the base and quote chain.
URL
Response
GET /timeouts
JSON object
Status Codes:
  • 200 OK
Response object:
  • timeouts: a JSON object with the pairs as keys and a JSON object with the timeouts as values
Examples:
GET /timeouts
Response:
{
"timeouts": {
"BTC/BTC": {
"base": {
"reverse": 144,
"swapMinimal": 144,
"swapMaximal": 288
},
"quote": {
"reverse": 144,
"swapMinimal": 144,
"swapMaximal": 288
}
},
"L-BTC/BTC": {
"base": {
"reverse": 1440,
"swapMinimal": 1440,
"swapMaximal": 2880
},
"quote": {
"reverse": 144,
"swapMinimal": 144,
"swapMaximal": 288
}
}
}
}

Swap Contracts

Currently Boltz only supports RSK Testnet
To query the addresses of contracts used by Boltz for swaps on EVM chains like RSK, the following endpoint can be queried:
URL
Response
GET /getcontracts
JSON object
Status Codes:
  • 200 OK
Response object:
  • rsk: a JSON object that contains all relevant RSK addresses
    • network: JSON object that contains information about the network
      • chainId: id of the RSK chain
    • swapContracts: JSON object containing swap contract addresses as values
    • tokens: JSON object with the ticker symbol of the supported token as key and its address as value
Examples:
GET /getcontracts
Response:
{
"rsk": {
"network": {
"chainId": 1337
},
"swapContracts": {
"EtherSwap": "0x165F8E654b3Fe310A854805323718D51977ad95F",
"ERC20Swap": "0x5F51247606d29Df75Af11475A85F7072f6472345"
},
"tokens": {
}
}
}

Fee Estimations

Boltz provides an API endpoint that returns fee estimations for all supported chains. These fee estimations are not enforced by Boltz and merely represent a recommendation.
For UTXO chains like Bitcoin it is important to mention that if 0-conf is accepted by Boltz for a particular pair and to be used with Normal Submarine Swaps, the lockup transaction has to have at least 80% of the recommended sat/vbyte value. One can read more about the what and why in the 0-conf docs.
URL
Response
GET /getfeeestimation
JSON object
Status Codes:
  • 200 OK
Response object:
This endpoint returns a JSON object of which each key is the symbol of a chain and each value the estimated fee for that chain denominated in sat/vbyte for UTXO chains like Bitcoin or GWEI for EVM chains like RSK.
Examples:
GET /getfeeestimation
Response:
{
"BTC": 16,
"L-BTC": 0.11
}

Raw Transactions

Boltz API also allows for querying raw transactions of all supported UTXO chains, irrespective of whether the transactions are still in the mempool or already included in a block. Note, that Boltz does not provide any kind of cryptographic proof that the transaction was included in a block. Also this call is primarily kept for backward compatibility with older integrations, it is not needed to construct transactions as the response of /swapstatus provides all necessary info.
Requests querying for transactions have to be POST and contain two arguments in its JSON encoded body:
  • currency: which chain should be queried for the transaction
  • transactionId: the id of the transaction that should be queried
URL
Response
POST /gettransaction
JSON object
Status Codes:
  • 200 OK
  • 400 Bad Request: if an argument wasn't provided or the transaction can't be found
Response object:
  • transactionHex: the requested transaction encoded in hex
Examples:
POST /gettransaction
Request body:
{
"currency": "BTC",
"transactionId": "0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098"
}
Response:
{
"transactionHex": "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0704ffff001d0104ffffffff0100f2052a0100000043410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac00000000"
}

Lockup Transactions

The following endpoint can be used to query the user's lockup transaction of a Normal Submarine Swap on UTXO chains. The request has to be POST and contain the following argument in the JSON encoded body:
  • id: id of the Submarine Swap
URL
Response
POST /getswaptransaction
JSON object
Status Codes:
  • 200 OK
  • 400 Bad Request: if an argument wasn't provided, or the Submarine Swap can't be found
Response object:
  • transactionHex: the lockup transaction of the Normal Submarine Swap encoded in hex
  • timeoutBlockHeight: block height at which the HTLC in the lockup transaction will time out
If the HTLC has not timed out yet, there will be an additional value in the response: