curl --request POST \
--url https://api.satora.io/swap/arkade/lightning \
--header 'Content-Type: application/json' \
--data '
{
"arkade_htlc_script_version": 123,
"refund_pk": "<string>",
"user_id": "<string>",
"extra_fees": 1,
"lightning_address": "<string>",
"lightning_invoice": "<string>",
"lnurl": "<string>",
"referral_code": "<string>",
"source_amount_sats": 123,
"target_amount_sats": 123
}
'import requests
url = "https://api.satora.io/swap/arkade/lightning"
payload = {
"arkade_htlc_script_version": 123,
"refund_pk": "<string>",
"user_id": "<string>",
"extra_fees": 1,
"lightning_address": "<string>",
"lightning_invoice": "<string>",
"lnurl": "<string>",
"referral_code": "<string>",
"source_amount_sats": 123,
"target_amount_sats": 123
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
arkade_htlc_script_version: 123,
refund_pk: '<string>',
user_id: '<string>',
extra_fees: 1,
lightning_address: '<string>',
lightning_invoice: '<string>',
lnurl: '<string>',
referral_code: '<string>',
source_amount_sats: 123,
target_amount_sats: 123
})
};
fetch('https://api.satora.io/swap/arkade/lightning', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.satora.io/swap/arkade/lightning",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'arkade_htlc_script_version' => 123,
'refund_pk' => '<string>',
'user_id' => '<string>',
'extra_fees' => 1,
'lightning_address' => '<string>',
'lightning_invoice' => '<string>',
'lnurl' => '<string>',
'referral_code' => '<string>',
'source_amount_sats' => 123,
'target_amount_sats' => 123
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.satora.io/swap/arkade/lightning"
payload := strings.NewReader("{\n \"arkade_htlc_script_version\": 123,\n \"refund_pk\": \"<string>\",\n \"user_id\": \"<string>\",\n \"extra_fees\": 1,\n \"lightning_address\": \"<string>\",\n \"lightning_invoice\": \"<string>\",\n \"lnurl\": \"<string>\",\n \"referral_code\": \"<string>\",\n \"source_amount_sats\": 123,\n \"target_amount_sats\": 123\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.satora.io/swap/arkade/lightning")
.header("Content-Type", "application/json")
.body("{\n \"arkade_htlc_script_version\": 123,\n \"refund_pk\": \"<string>\",\n \"user_id\": \"<string>\",\n \"extra_fees\": 1,\n \"lightning_address\": \"<string>\",\n \"lightning_invoice\": \"<string>\",\n \"lnurl\": \"<string>\",\n \"referral_code\": \"<string>\",\n \"source_amount_sats\": 123,\n \"target_amount_sats\": 123\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.satora.io/swap/arkade/lightning")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"arkade_htlc_script_version\": 123,\n \"refund_pk\": \"<string>\",\n \"user_id\": \"<string>\",\n \"extra_fees\": 1,\n \"lightning_address\": \"<string>\",\n \"lightning_invoice\": \"<string>\",\n \"lnurl\": \"<string>\",\n \"referral_code\": \"<string>\",\n \"source_amount_sats\": 123,\n \"target_amount_sats\": 123\n}"
response = http.request(request)
puts response.read_body{
"arkade_htlc_script_version": 123,
"arkade_server_pk": "<string>",
"arkade_vhtlc_address": "<string>",
"client_lightning_invoice": "<string>",
"created_at": "2023-11-07T05:31:56Z",
"fee_sats": 123,
"hash_lock": "<string>",
"id": "<string>",
"invoice_expires_at": 123,
"network": "<string>",
"network_fee_sats": 123,
"receiver_pk": "<string>",
"sender_pk": "<string>",
"source_amount": "<string>",
"source_token": {
"chain": "Arkade",
"decimals": 1,
"name": "<string>",
"symbol": "<string>",
"token_id": "btc"
},
"status": "pending",
"target_amount": "<string>",
"target_token": {
"chain": "Arkade",
"decimals": 1,
"name": "<string>",
"symbol": "<string>",
"token_id": "btc"
},
"unilateral_claim_delay": 123,
"unilateral_refund_delay": 123,
"unilateral_refund_without_receiver_delay": 123,
"vhtlc_refund_locktime": 123,
"arkade_claim_txid": "<string>",
"arkade_fund_txid": "<string>"
}{
"error": "<string>"
}{
"error": "<string>"
}{
"error": "<string>"
}{
"error": "<string>"
}Create a new Arkade-to-Lightning swap.
The user locks Arkade VTXOs in a VHTLC and receives BTC on their Lightning invoice. Flow:
- User funds the returned Arkade VHTLC (locked to the invoice’s payment hash)
- Server pays the invoice; the settled payment reveals the preimage
- Server claims the VHTLC with the preimage
If the payment fails the swap becomes ServerWontFund and the user
reclaims their VTXOs via the collaborative refund endpoint (or
unilaterally after the refund locktime).
curl --request POST \
--url https://api.satora.io/swap/arkade/lightning \
--header 'Content-Type: application/json' \
--data '
{
"arkade_htlc_script_version": 123,
"refund_pk": "<string>",
"user_id": "<string>",
"extra_fees": 1,
"lightning_address": "<string>",
"lightning_invoice": "<string>",
"lnurl": "<string>",
"referral_code": "<string>",
"source_amount_sats": 123,
"target_amount_sats": 123
}
'import requests
url = "https://api.satora.io/swap/arkade/lightning"
payload = {
"arkade_htlc_script_version": 123,
"refund_pk": "<string>",
"user_id": "<string>",
"extra_fees": 1,
"lightning_address": "<string>",
"lightning_invoice": "<string>",
"lnurl": "<string>",
"referral_code": "<string>",
"source_amount_sats": 123,
"target_amount_sats": 123
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
arkade_htlc_script_version: 123,
refund_pk: '<string>',
user_id: '<string>',
extra_fees: 1,
lightning_address: '<string>',
lightning_invoice: '<string>',
lnurl: '<string>',
referral_code: '<string>',
source_amount_sats: 123,
target_amount_sats: 123
})
};
fetch('https://api.satora.io/swap/arkade/lightning', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.satora.io/swap/arkade/lightning",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'arkade_htlc_script_version' => 123,
'refund_pk' => '<string>',
'user_id' => '<string>',
'extra_fees' => 1,
'lightning_address' => '<string>',
'lightning_invoice' => '<string>',
'lnurl' => '<string>',
'referral_code' => '<string>',
'source_amount_sats' => 123,
'target_amount_sats' => 123
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.satora.io/swap/arkade/lightning"
payload := strings.NewReader("{\n \"arkade_htlc_script_version\": 123,\n \"refund_pk\": \"<string>\",\n \"user_id\": \"<string>\",\n \"extra_fees\": 1,\n \"lightning_address\": \"<string>\",\n \"lightning_invoice\": \"<string>\",\n \"lnurl\": \"<string>\",\n \"referral_code\": \"<string>\",\n \"source_amount_sats\": 123,\n \"target_amount_sats\": 123\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.satora.io/swap/arkade/lightning")
.header("Content-Type", "application/json")
.body("{\n \"arkade_htlc_script_version\": 123,\n \"refund_pk\": \"<string>\",\n \"user_id\": \"<string>\",\n \"extra_fees\": 1,\n \"lightning_address\": \"<string>\",\n \"lightning_invoice\": \"<string>\",\n \"lnurl\": \"<string>\",\n \"referral_code\": \"<string>\",\n \"source_amount_sats\": 123,\n \"target_amount_sats\": 123\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.satora.io/swap/arkade/lightning")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"arkade_htlc_script_version\": 123,\n \"refund_pk\": \"<string>\",\n \"user_id\": \"<string>\",\n \"extra_fees\": 1,\n \"lightning_address\": \"<string>\",\n \"lightning_invoice\": \"<string>\",\n \"lnurl\": \"<string>\",\n \"referral_code\": \"<string>\",\n \"source_amount_sats\": 123,\n \"target_amount_sats\": 123\n}"
response = http.request(request)
puts response.read_body{
"arkade_htlc_script_version": 123,
"arkade_server_pk": "<string>",
"arkade_vhtlc_address": "<string>",
"client_lightning_invoice": "<string>",
"created_at": "2023-11-07T05:31:56Z",
"fee_sats": 123,
"hash_lock": "<string>",
"id": "<string>",
"invoice_expires_at": 123,
"network": "<string>",
"network_fee_sats": 123,
"receiver_pk": "<string>",
"sender_pk": "<string>",
"source_amount": "<string>",
"source_token": {
"chain": "Arkade",
"decimals": 1,
"name": "<string>",
"symbol": "<string>",
"token_id": "btc"
},
"status": "pending",
"target_amount": "<string>",
"target_token": {
"chain": "Arkade",
"decimals": 1,
"name": "<string>",
"symbol": "<string>",
"token_id": "btc"
},
"unilateral_claim_delay": 123,
"unilateral_refund_delay": 123,
"unilateral_refund_without_receiver_delay": 123,
"vhtlc_refund_locktime": 123,
"arkade_claim_txid": "<string>",
"arkade_fund_txid": "<string>"
}{
"error": "<string>"
}{
"error": "<string>"
}{
"error": "<string>"
}{
"error": "<string>"
}Body
Arkade VHTLC script version. New swaps must use version 1.
User's refund public key for the Arkade VHTLC (sender role).
User ID derived from wallet for recovery purposes
Optional per-swap fee surcharge in basis points (0..=max_extra_fee_bps configured on the matching developer key).
x >= 0Lightning address (user@domain) to resolve into an invoice over
the payout amount. Mutually exclusive with the other destination
fields.
BOLT11 invoice the user wants paid. Must carry an amount (which
pins the payout — source_amount_sats cannot be combined with it).
Mutually exclusive with lightning_address and lnurl.
LNURL-pay string to resolve into an invoice over the payout amount. Mutually exclusive with the other destination fields.
Optional referral code for fee exemption
Total amount the user wants to lock on Arkade in satoshis (fees are
deducted from the Lightning payout — use this for send-max flows).
Only valid with lightning_address/lnurl; mutually exclusive
with target_amount_sats.
Amount the recipient should receive over Lightning in satoshis
(fees are added on top). Required with lightning_address/lnurl
unless source_amount_sats is given; optional with
lightning_invoice, where it must match the invoice amount.
Response
Swap created successfully
Arkade → Lightning swap response.
Arkade server's public key
Arkade VHTLC address the user must fund
BOLT11 invoice the server will pay once the VHTLC is funded
Timestamp of when the swap was created
Protocol fee in satoshis
Hash lock (0x-prefixed 32-byte hex; the invoice's payment hash)
Unique swap identifier
Unix timestamp after which the invoice can no longer be paid
Bitcoin network
Flat network fee in satoshis; the provider's actual Lightning send
fee is paid out of fee_sats + network_fee_sats, never on top
Server's VHTLC public key (receiver in the VHTLC)
User's refund public key (sender in the VHTLC)
Amount the user must lock in the Arkade VHTLC in satoshis
Source token info
Show child attributes
Show child attributes
Current status of the swap
pending, clientfundingseen, clientfunded, clientrefunded, serverfunded, clientredeeming, clientredeemed, serverredeemed, clientfundedserverrefunded, clientrefundedserverfunded, clientrefundedserverrefunded, expired, clientinvalidfunded, clientfundedtoolate, serverwontfund, clientredeemedandclientrefunded Amount paid out on the user's Lightning invoice in satoshis
Target token info
Show child attributes
Show child attributes
VHTLC refund locktime (unix timestamp)
Arkade VHTLC claim transaction ID (server claim)
Arkade VHTLC fund transaction ID (user funding)