LIGHTNING-SENDONION(7)
π§ LIGHTNING-SENDONION(7) π§
okay bestie, this is the manual page for sendonion β yes, the LIGHTNING-SENDONION(7) one. Itβs giving custom onion packet energy, and honestly? iconic. π
πΈ NAME πΈ
sendonion β send a payment with a custom onion packet.
β¨ SYNOPSIS β¨
sendonion onion first_hop payment_hash [label] [shared_secrets] [partid]
[bolt11] [amount_msat] [destination] [localinvreqid] [groupid]
[description] [total_amount_msat]
π DESCRIPTION π
β οΈ real talk: you probably want the more modern and flexible injectpaymentonion command instead of this one. not me warning you before you get attached. π
The sendonion RPC command can be used to initiate a payment attempt with a custom onion packet. The onion packet is used to deliver instructions for hops along the route on how to behave. Normally these instructions are indications on where to forward a payment and what parameters to use, or they contain details of the payment for the final hop. However, itβs possible to add arbitrary information for hops in the custom onion, which allows for custom extensions that are not directly supported by Core Lightning. slay, honestly. π
If the first element of route does not have "channel" set, a suitable channel (if any) will be chosen; otherwise that specific short-channel-id is used. Hereβs an example of a 3 hop onion:
[
"298606954e9de3e9d938d18a74fed794c440e8eda82e52dc08600953c8acf9c4",
"2dc094de72adb03b90894192edf9f67919cb2691b37b1f7d4a2f4f31c108b087",
"a7b82b240dbd77a4ac8ea07709b1395d8c510c73c17b4b392bb1f0605d989c85"
]
onion(hex) β a hex-encoded 1366 bytes long blob that was returned by either of the tools that can generate onions. It contains the payloads destined for each hop and some metadata. Please refer to BOLT 04 for further details. It is specific to the route that is being used and thepayment_hashused to construct it, and therefore cannot be reused for other payments or to attempt a separate route. The custom onion can generally be created using thedevtools/onionCLI tool, or thecreateonionRPC command. π§first_hop(object) β instructs Core Lightning which peer to send the onion to. It is a JSON dictionary that corresponds to the first element of theroutearray returned bygetroute(so fields not mentioned here are ignored).id(pubkey) β node id for the peer. Use any available channel available to this peer.amount_msat(msat) β the amount to add an HTLC for β millisatoshis.delay(u16) β the number of blocks of delay on top of the current blockheight.
payment_hash(hash) β specifies the 32 byte hex-encoded hash to use as a challenge to the HTLC that we are sending. It is specific to the onion and has to match the one the onion was created with. πlabel(string, optional) β can be used to provide a human readable reference to retrieve the payment at a later time.shared_secrets(array of secrets, optional) β a JSON list of 32 byte hex-encoded secrets that were used when creating the onion. Core Lightning can send a payment with a custom onion without the knowledge of these secrets, however it will not be able to parse an eventual error message since that is encrypted with the shared secrets used in the onion. π Ifshared_secretsis provided, Core Lightning will decrypt the error, act accordingly, e.g., add achannel_updateincluded in the error to its network view, and set the details inlistsendpayscorrectly. If it is not provided, Core Lightning will store the encrypted onion, and expose it inlistsendpaysallowing the caller to decrypt it externally. If it is not provided, the Core Lightning node does not know how long the route is, which channels or nodes are involved, and what an eventual error could have been. It can therefore be used for oblivious payments. πsecret(optional) β yep, thatβs the nested type.
partid(u16, optional) β if provided and non-zero, allows for multiple parallel partial payments with the samepayment_hash.bolt11(string, optional) β if provided, it will be returned inwaitsendpayandlistsendpaysresults.amount_msat(msat, optional) β used to annotate the payment, and is returned bywaitsendpayandlistsendpays.destination(pubkey, optional) β if provided, it will be returned inlistpaysresult.localinvreqid(hash, optional) βlocalinvreqidis used by offers to link a payment attempt to a localinvoice_requestoffer created bylightningd-invoicerequest(7).groupid(u64, optional) β grouping key to disambiguate multiple attempts to pay an invoice or the samepayment_hash.description(string, optional) β if provided, it will be returned inwaitsendpayandlistsendpaysresults. (added v0.11.0)total_amount_msat(msat, optional) β this is the full amount requested by the destination in the invoice. It is needed internally for multi-part payments. Its default value is0 msatfor backwards compatibility. The default is0. (added v25.05)
π RETURN VALUE π
On success, an object is returned, containing:
created_index(u64) β 1-based index indicating order this payment was created in. (added v23.11)id(u64) β old synonym forcreated_index.payment_hash(hash) β the hash of thepayment_preimagewhich will prove payment.status(string) (one of"pending","complete") β status of the payment (could be complete if already sent previously).created_at(u64) β the UNIX timestamp showing when this payment was initiated.amount_sent_msat(msat) β the amount sent.amount_msat(msat, optional) β the amount delivered to destination (if known).destination(pubkey, optional) β the final destination of the payment if known.label(string, optional) β the label, if given tosendpay.bolt11(string, optional) β thebolt11string (if supplied).bolt12(string, optional) β thebolt12string (if supplied).partid(u64, optional) β thepartid(if supplied) tosendonion/sendpay.
π¦ If status is "complete":
payment_preimage(secret) β the proof of payment: SHA256 of thispayment_hash.updated_index(u64, optional) β 1-based index indicating order this payment was changed. (added v23.11)
π If status is "pending":
message(string, optional) β monitor status withlistpaysorwaitsendpay.
π ERRORS π
The following error codes may occur:
202β an parseable onion
the error details are decrypted and presented here, if shared_secrets was provided and an error was returned by one of the intermediate nodes
π AUTHOR π
Christian Decker decker.christian@gmail.com is mainly responsible.
π«Ά SEE ALSO π«Ά
lightning-injectpaymentonion(7), lightning-createonion(7), lightning-sendpay(7), lightning-listsendpays(7)
π RESOURCES π
Main web site: https://github.com/ElementsProject/lightning
π EXAMPLES π
ok bestie, real talk β this is where it gets good. we're gonna walk through an actual sendonion call, and yes, the onion blob is genuinely that long. it's giving "I contain multitudes" π
don't panic, just copy it exactly and trust the process.
β¨ Example 1 β¨
π€ Request
so first you hit the CLI. -k means you're passing named params (key=value style, iconic), and you hand over three of them: the onion itself, the first_hop as a lil JSON object, and the payment_hash. watch how the quoting works β double quotes for the simple ones, single quotes wrapping the JSON so it stays one argument:
$ lightning-cli sendonion -k "onion"="onion1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010" "first_hop"='{"id": "nodeid020202020202020202020202020202020202020202020202020202020202", "channel": "109x1x1", "direction": 1, "amount_msat": 1002, "delay": 21, "style": "tlv"}' "payment_hash"="assocdata0010101010101010101010101010101010101010101010101010101"
and here's what those params look like when they get all parsed and pretty β same data, just unfolded so you can actually read it π:
{
"id": "example:sendonion#1",
"method": "sendonion",
"params": {
"onion": "onion1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010",
"first_hop": {
"id": "nodeid020202020202020202020202020202020202020202020202020202020202",
"channel": "109x1x1",
"direction": 1,
"amount_msat": 1002,
"delay": 21,
"style": "tlv"
},
"payment_hash": "assocdata0010101010101010101010101010101010101010101010101010101"
}
}
π₯ Response
and then it comes back like this π:
{
"message": "Monitor status with listpays or waitsendpay",
"created_index": 10,
"id": 10,
"payment_hash": "assocdata0010101010101010101010101010101010101010101010101010101",
"groupid": 1,
"amount_sent_msat": 1002,
"created_at": 1738000000,
"status": "pending"
}
look at that "status": "pending" β it's not done yet, bestie, it's pending. the message is literally telling you what to do next: go check on it with listpays or waitsendpay. main character energy is knowing when to follow up π
and that's the whole thing! you made it through the wall of 1010s, I'm so proud π«Ά this page was served up by Core Lightning v26.06.9 as LIGHTNING-SENDONION(7) β go forth and route some onions, you absolute icon π
β¨
π¦ where this page comes from
- nixpkgs unstable: clightning 26.06.9
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms