Developer Guide
Migration Guide
15 min
migrating from direct lnd who this guide is for you're currently integrating directly with lnd — via grpc, rest, or lncli — using tls certificates and macaroons for authentication you want to move to the voltage payments api, which gives you a single rest api for sending and receiving payments without managing grpc stubs, protobuf definitions, macaroon files, or route finding logic this guide covers what changes regardless of your target setup, then links you to the step by step path that fits your needs why migrate payments api vs direct lnd before diving into the how, here's what you gain by moving from direct lnd to the payments api built in accounts and fund segregation with direct lnd, your node has a single on chain wallet and a single pool of channel liquidity if you serve multiple customers, products, or use cases, you need to build a double entry ledger system on top of lnd to track who owns what this is complex, error prone, and a significant engineering investment the payments api gives you wallets — each with its own tracked balance — all backed by a single node fund segregation is handled for you at the api layer you can create as many wallets as you need per environment without building or maintaining your own accounting system webhooks for payment notifications lnd doesn't have native webhooks to know when a payment arrives or completes, you either poll or hold open a grpc stream ( subscribeinvoices , subscribechannelevents ) and manage reconnection logic yourself the payments api delivers real time webhook notifications — http post requests to your endpoint for every payment event paired with a lightweight reconciliation loop as a safety net, this gives you reliable, event driven payment monitoring without managing persistent connections payments abstracted from node liquidity when you use lnd directly, every payment forces you to think about the underlying plumbing channel balances, inbound vs outbound liquidity, utxo management, fee estimation, route finding your application code is tightly coupled to node operations the payments api separates payment logic from liquidity management your application talks to wallets and payments — clean balances, simple send/receive calls, payments that just work the lnd node operates underneath as a liquidity reserve, but those concerns are isolated you (and voltage, via the support macaroon) manage channels and capacity separately from your payment integration with a credit backed setup, this separation goes even further — there's no node to manage at all with a node backed setup, you still handle liquidity, but your payment code never has to know about it choose your migration path there are two ways to use the voltage payments api choose based on whether you want to keep running your own node node backed credit backed plan required enterprise enterprise + line of credit approval infrastructure you keep your voltage lnd node no node — voltage handles it funding your node's on chain + channel balance line of credit (collateral backed) channel management you + voltage (via support macaroon) not needed liquidity you manage treasury; voltage assists not needed usd support btc only btc wallets or usd reconciliation best for teams that need full node control, existing channel relationships, or custom routing teams that want zero infrastructure overhead and/or usd denominated payments ready to start? docid\ brko wdxk1diopuqwmffs — keep your node, use the api docid\ ppmdft3 otgsnxz7ai6ry — drop your node, use a line of credit what changes (both paths) the sections below apply to both migration paths read through them before starting your step by step guide authentication before (direct lnd) after (payments api) transport tls (self signed or ca signed cert) https (standard tls, no cert file needed) credential macaroon (admin, invoice, readonly, or custom baked) x api key header credential format binary or hex encoded file string token scope per macaroon permission caveats per environment api key rotation lncli bakemacaroon or changepassword rpc generate new key in dashboard before curl cacert tls cert \\ \ header "grpc metadata macaroon $(xxd ps u c 1000 admin macaroon)" \\ https //your node voltage cloud 8080/v1/balance/channels after curl 'https //voltageapi com/v1/organizations/{organization id}/environments/{environment id}/payments' \\ \ header 'x api key your api key' concept mapping reference this table maps every common lnd operation to its payments api equivalent lnd method lnd rest path payments api equivalent notes addinvoice post /v1/invoices post /payments with payment kind use payment kind "bolt11" for lightning response is 202; fetch with get to retrieve the invoice string sendpaymentv2 post /v2/router/send post /payments with type "bolt11" no route hints or fee limits to manage beyond max fee status via get or webhooks instead of streaming decodepayreq get /v1/payreq/{pay req} not applicable the payments api handles invoice parsing internally if you need to inspect an invoice before paying, decode it client side or use a library newaddress post /v1/newaddress post /payments with payment kind "onchain" (receive) creates a receive payment that includes a bitcoin address in the response sendcoins post /v1/transactions post /payments with type "onchain" amount in msats via the amount object, not satoshis subscribeinvoices get /v1/invoices/subscribe webhooks + reconciliation loop see "the big shift" below subscribe to receive completed , receive expired , etc lookupinvoice get /v1/invoice/{r hash} get /payments/{payment id} look up by your payment id (uuid), not by payment hash listpayments get /v1/payments get /payments?direction=send supports filtering by statuses\[] , wallet id , pagination via offset / limit listinvoices get /v1/invoices get /payments?direction=receive same endpoint, different direction filter walletbalance get /v1/balance/blockchain get /wallets/{wallet id} returns wallet balance for node backed setups you can still check on chain balance via lnd directly channelbalance get /v1/balance/channels get /wallets/{wallet id} the payments api exposes a single wallet balance channel level detail is available through lnd directly (node backed only) listchannels get /v1/channels not applicable channel management stays on lnd (node backed) or is not applicable (credit backed) openchannel / closechannel post /v1/channels / delete /v1/channels/{channel point} not applicable same as above getinfo get /v1/getinfo not applicable node level info (pubkey, alias, sync status) is an lnd concern, not a payments api concern the big shift streaming → webhooks + polling this is the biggest architectural change in the migration lnd uses long lived grpc streams; the payments api uses webhooks backed by a reconciliation loop how monitoring works today (direct lnd) you open a grpc stream ( subscribeinvoices , subscribechannelevents , etc ) and process events as they arrive if the stream drops, you reconnect and may need to replay from an index how monitoring works with the payments api webhooks (primary) — voltage sends http post requests to your endpoint for each event ( send succeeded , receive completed , etc ) reconciliation loop (safety net) — a cron job periodically lists payments updated since your last checkpoint, catching anything your webhook handler missed ad hoc polling (optional) — get /payments/{payment id} for on demand status checks recommended architecture a webhook handler that receives events and upserts payments into your database keyed on payment id a reconciliation cron (every 1–5 minutes) that lists recently updated payments and upserts them the same way both paths write to the same table using the same idempotent upsert logic the webhook gives you real time speed; the recon loop guarantees completeness before (grpc streaming) after (webhooks + recon) connection model persistent bidirectional stream stateless http posts to your endpoint missed events must track stream index and replay on reconnect reconciliation loop catches missed deliveries automatically latency sub second (same connection) sub second (webhook) to minutes (recon loop) reliability depends on stream stability and your reconnect logic voltage retries failed deliveries; recon loop as safety net auth macaroon on the stream shared secret for webhook signature verification; x api key for recon polling event granularity per invoice or per payment updates per event types send succeeded , send failed , receive generated , receive completed , receive expired , receive failed , etc for webhook setup details, signature verification, and reconciliation loop implementation, see the guide payment status changes the payments api uses different status names than lnd send payments lnd status payments api status meaning in flight sending payment is being routed succeeded completed payment delivered failed failed routing failed or timed out receive payments lnd status payments api status meaning (invoice created) generating invoice/address being created open / accepted receiving invoice issued, waiting for payment settled completed payment received and credited canceled expired invoice expired unpaid (error) failed generation or receipt failed amount handling lnd works in satoshis (and sometimes millisatoshis as separate fields) the payments api uses an amount object everywhere { "amount" 150000, "currency" "btc", "unit" "msats" } all btc amounts use millisatoshis as the base unit usd amounts use cents as the base unit ( "currency" "usd", "unit" "cents" ) legacy fields amount msats and amount sats are accepted but deprecated — use the amount object conversion reference 1 sat = 1,000 msats if your lnd code sends 15,000 sats, the equivalent payments api amount is 15000000 msats what you can remove after migrating, you can delete the following from your codebase and infrastructure tls certificate management — no cert files to load, rotate, or distribute macaroon loading and injection — no binary token files; just an api key string grpc / protobuf setup — no proto files, code generation, or grpc client libraries route finding and path optimization — the payments api handles routing invoice decoding — the api parses invoices internally channel rebalancing logic — handled by voltage (node backed with support macaroon) or not applicable (credit backed) fee estimation — max fee defaults are sensible; no manual fee rate lookups needed stream reconnection logic — webhooks replace grpc streams next steps pick your path and follow the step by step guide docid\ brko wdxk1diopuqwmffs — keep your node, use the api docid\ ppmdft3 otgsnxz7ai6ry — drop your node, use a line of credit