As explained in How-to integrate page, you need to follow some steps so your LiveApp can communicate properly with our Backend.

In addition to the following steps, Ledger also needs to know:

  • The base url of the API,
  • Any backend authentication information to use the api (token in header...)

Endpoints needed for Sell

In order to communicate with Ledger’s backend, you must provide standardised APIs for Ledger's SELL aggregator services to call.


You will find all the information regarding the SELL endpoints here: (opens in a new tab).

There are 4 main endpoints needed for the sell:

Additional Details: POST /sell

Your Protobuf message should have the following structure:

syntax = "proto3";
package ledger_sell;
// (coefficient) * 10^(- exponent)
message UDecimal {
    bytes  coefficient = 1;
    uint32 exponent = 2;
message NewSellResponse {
    string   trader_email = 1;           
    string   in_currency = 2;            
    bytes    in_amount = 3;              
    string   in_address = 4;             
    string   out_currency = 5;           
    UDecimal out_amount = 6;             
    bytes    device_transaction_id = 7;  

Payload & Signature

Here is a little diagram to explain how the payload and the signature are generated:

Payload and Payload Signature generation diagram

Signature usage

  • Payload and Signature
    From the provider to Ledger Live. The payload is a protobuf message containing the trade data. It is generated by the provider and sent to Ledger Live.
type Payload struct {
R, S := Sign(payload, privKey)
  • Validate
    Exchange app checks and validates the payload (signature and content).
// Compare nonce in payload
Verify((R, S), payload, pubKey)
  • Display
    Exchange app requests approval to the user by displaying the operation summary on screen.
Send currency_from amount_to_provider
Receive currency_to amount_to_wallet

Input field: nonce

A nonce field will be passed as a parameter of the /swap endpoint.
It is a 32 bytes nonce which is generated by the hardware wallet to avoid replay attacks.
It will be base 64 URL encoded before being sent to the /swap endpoint.

Output field: providerSig

The real return value of the /swap endpoint is the providerSig field with the JSON Web Signature (JWS) in compact form within:

  • providerSig.payload - base64 URL of the binary serialized protobuf message.NewTransactionResponse.
  • providerSig.signature - base64 URL of the ES256 signature of providerSig.payload. More details in the JWS signature section.


The output field is providerSig, and is based on the flattened JWS JSON (opens in a new tab), without the optional protected and header parameters.

The algorithms supported by Ledger are ES256 (opens in a new tab) with secp256k1 or secp256r1 curve. There is no need to specify them into the header, as we will store your public key with this information in our system.

As specified in the JWA spec, the signature is a concatenation of the (R, S) pair in a 64 octets array, and not the ASN1 format.

The JWS RFC (opens in a new tab) requires the signature to be computed on: <BASE64URL_HEADER>.<BASE64URL_PAYLOAD>. As we don't require any header, the signature has to be computed on: .<BASE64URL_PAYLOAD>.

Copyright © Ledger SAS. All rights reserved. Ledger, Ledger Nano S, Ledger Vault, Bolos are registered trademarks of Ledger SAS