What do we need ?
In order to become a swap provider in the Ledger Live ecosystem, you must:
- Submit your API following Ledger’s specifications. We will guide you through the requirements and the modifications you will need to apply to your API before sending it to us.
- Provide to Ledger your public key that will be used to encode the swap info.
- Submit your LiveApp following Ledger’s specfication.
This diagram shows what is needed from the provider’s side in order to interact with Ledger Live.

Provider’s Endpoints
In order to communicate with Ledger’s back-end, you have to give us the mapping of the endpoints we need.
As you can see on the diagram above, there are 4 main endpoints needed for the swap:
- To get the list of available currencies: /currencies.
- To get the list of tradable pairs: /pairs.
- To query a rate: /quote.
- To query a swap status: /status.
You will find the details about each needed endpoint below.
GET /currencies
- Function: Returns a list of supported currencies.
- Input: –
- Output: Array of supported currencies, with information required to uniquely identify coins/tokens.
- Payload:
[
{
"id":"BTC",
"type":"coin",
"blockchain":"bitcoin",
"chainId":1
},
{
"id":"USDC",
"type":"token",
"blockchain":"ethereum",
"chainId":1,
"contract":"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"
}
]
GET /pairs
- Function: Returns a list of supported pairs. This endpoint is not required if all permutations returned by /currencies are supported.
- Input: –
- Output: Array of supported swap pairs, with supported quote type (
fixed
/ float
).
- Payload:
[
{
"from":"btc",
"to":"bat",
"tradeMethod":[
"fixed",
"float"
]
},
{
"from":"bat",
"to":"btc",
"tradeMethod":[
"fixed",
"float"
]
}
]
Fixed quote: The quote price is guaranteed until execution (or until end of quote validity period).
Float quote: The quote price is indicative only, real price is computed at execution time
POST /quote
- Function: Returns a quote for a pair and amount.
- Input:
from
, to
, amount
.
- Output:
method
: fixed
or float
(optional, only required for consistency check)
quoteId
: quote unique identifier (optional, only required for fixed quotes)
expiry
: quote expiration timestamp (optional, only required for fixed quotes)
minAmountFrom
: minimum valid amount
for this pair (optional, only required if amount is too low)
maxAmountFrom
: maximum valid amount
for this pair (optional, only required if amount is too large)
amountFrom
: should be same as amount
(optional, only required for consistency check) (as an input coin floating amount)
amountTo
: estimated output amount that will be sent to user (as an output coin floating amount)
payoutNetworkFees
: estimated gas fees that will be used for the payout transaction (as an output coin floating amount)
- Payload:
- Success
{
"quoteId":"id1",
"from":"btc",
"to":"bat",
"amountFrom":"1",
"amountTo":"40000",
"payoutNetworkFees": "0.0002",
"rate":"37800.21",
"tradeMethod":"float",
"expiry": "date"
}
Note: the final estimated amount received by the user should be amountTo - payoutNetworkFees
.
Some requirements about the /quote endpoint:
- The quote must work without user auth. It can require a Ledger auth.
- The quote must be valid long enough (at least a few minutes).
GET /status
- Function: Returns the status of an executed swap transaction.
- Input:
swapId
.
- Output:
status
:
FINISHED
: Trade has been completed successfully (user has received payout transaction).
EXPIRED
: Payin transaction was not received in time, trade is cancelled. User will be refunded if payin transaction is received afterwards.
ON_HOLD
: Trade has been put on hold (eg: for KYC reasons). User must contact support.
PENDING
: Trade is in progress (partner is waiting to receive payin transaction, or user is waiting to receive payout transaction)
REFUNDED
: Trade has been cancelled, refund transaction has been successfully received by user.
UNKNOWN
: Trade is in unknown state. User must contact support.
amount
: as soon as this information is known, this should contain the final amount transferred to the user in output currency
payinTransactionId
: as soon as this information is known, this should contain the payin transaction hash
payoutTransactionId
: as soon as this information is known, this should contain the payout transaction hash
- Payload:
- Success
{
"quoteId":"id1",
"status":"FINISHED",
"amount": 1.337,
"payinTransactionId": "0xfffffffffffff",
"payoutTransactionId": "0xfffffffffffff"
}
Ledger’s Endpoint
To complete the transaction, you need to provide to the LiveApp SDK a payload that will be signed by the user’s device (e.g. Ledger Nano).
POST /swap/payload
- Function: Create a binary payload which contains all information needed to fullfil a swap transaction.
- Input:
provider
: your id or name known by Ledger for identification purpose.
swapId
: provider’s id of the ongoing swap transaction. This will be used by Ledger’s backend to retrieve the status of user swap transaction.
payinAddress
: provider’s address.
refundAddress
: refund address.
payoutAddress
: payout transaction address.
currencyFrom
: from currency id, using your identifiers.
currencyTo
: to currency id, using you identifiers.
amountToProvider
: amount of currencyFrom
that the provider expects to receive from client.
amountToWallet
: amount of currencyTo
that the provider agrees to send to the client in exchange from amountToProvider
. This amount must also include the network fees that the provider will pay to send the crypto to the user.
nonce
: value to use for device_transaction_id
field in the protobuf payload.
- Output: payload in a binary format.
In case of an error, returns the same payload as /check_quote.
Provider’s LiveApp
The LiveApp needs to respond to a deeplink with some parameters.
The deeplink format is already fixed and will depend on the information you provided inside your LiveApp manifest (ex: ledgerlive://discover/swapprovidername
).
The query params for this deeplink are:
quoteId
: The id retrieved by Ledger’s backend during a quote request
fromAddress
: The user’s address that will be used for the payin transaction.
toAddress
: The user’s address that will be used for the payout transaction.
Example: ledgerlive://discover/swapprovidername?quoteId=1234&fromAddress=0xFFFFFFF&toAddress=0xFFFFFFF
Ledger’s WalletAPI SDK
To learn how to create (or embed if already existing) your user interface for the swap, please follow this tutorial.
Your LiveApp will interact with Ledger Live with 2 differents methods:
Those methods are more detailed in github
startExchange
This method will return you a nonce.
A nonce field will is the last parameter you need to provide to the /swap endpoint.
It is a 32 bytes nonce which is generated by the hardware wallet to avoid replay attacks.
It needs to be base 64 URL encoded before being sent to the /swap endpoint.
completeExchange
This method will need you to provide, among other things, 2 important parameters:
- payload: it is the base64 URL encoded result of your call to the /swap/payload endpoints.
- signature: it is the base64 URL encoded result of your JWS signature of the previous payload.
Here is a little diagram to explain how the payload
and its signature
are generated:

payload
: the trade parameters are assembled in a protobuf message, via the /swap/payload endpoint. Then, with base64 encoding we get the payload
field.
signature
: trom the binary encoding of the previous protobuf (Byte Array), we sign it with ES256 and the provider’s private key to get a Signature Byte Array. Finally, with base64 encoding we get the signature
.
Test your LiveApp
Thanks to the Developer Mode and the debug-app, you can easily test your integration inside Ledger Live environment.
If you need more info, please check our How to - Test tutorial. You should find everything you need there.