Nonce v2 Rollout

We have introduced Nonce v2, an improved version of the nonce parameter included in the Auth header payload.

Why Nonce v2?

We're improving how we protect your requests to enhance security and efficiency. Nonce v1 worked well, but users sending many requests —like our high-traffic power users— sometimes experienced valid actions being flagged as suspicious. That's not ideal. Nonce v2 resolves this issue, ensuring a smoother experience while maintaining rock-solid security.

What does Nonce v2 improve?

Here's why you will love the change:

  • Fewer Rejected Requests: Valid requests won't be blocked just because they arrive out of order—ideal for users sending multiple calls.
  • Top-Notch Security: It still prevents replay attacks (those sneaky repeat attempts), keeping your account safe.
  • Smoother Workflow: It handles real-world usage efficiently, whether sending one request or a hundred.

Nonce v2 focuses on reliability and flexibility, adapting to how you use our APIs.

How does it affect me?

The transition to Nonce v2 is straightforward. Simply update how you generate nonce values (explained further down). Once updated, you will seamlessly be using Nonce v2, a more reliable mechanism with the same strong protection.

How can I use Nonce v2?

The same header currently supporting Nonce v1 will also support Nonce v2. To integrate with the improved validation process, send nonce values with the Nonce v2 format. For details, refer to the provided examples.

When can I start using Nonce v2?

Right now.

What does Nonce v2 look like?

Nonce v2 is a number between 14 and 19 digits, formed by concatenating:

  • A 13-digit Epoch timestamp in milliseconds (for example, 1731349200123 for March 11, 2025, 12:00:00.123 UTC).
  • A random salt (1 to 6 digits, for example, 123456).

Examples:

  • 19 digits: 1731349200123123456 (timestamp 1731349200123 + salt 123456)
  • 18 digits: 173134920012378901 (timestamp 1731349200123 + salt 78901)
  • 16 digits: 1731349200123999 (timestamp 1731349200123 + salt 999)

Bitso recommends a 6-digit salt for maximum entropy.

Will Nonce v1 be deprecated?

Yes, we will deprecate Nonce v1 in November 2025. After this date, the service will reject all Nonce v1 validations, so be sure to switch to Nonce v2 before then.

Examples of Nonce v2 Generation

Below are examples in various programming languages demonstrating how to generate a Nonce v2 value according to the specification (13-digit Epoch timestamp in milliseconds + up to 6-digit random salt).

Each example includes comments explaining the process and an example output.

import java.time.Instant;

public class NonceV2Generator {
    public static String generateNonceV2() {
        // Get current timestamp in milliseconds (13 digits)
        long timestamp = Instant.now().toEpochMilli();
      
        // Generate random salt (up to 6 digits, here using 6 digits for consistency)
        int salt = (int) (Math.random() * 900000) + 100000; // Range: 100000-999999
      
        // Concatenate timestamp and salt
        return String.format("%d%d", timestamp, salt);
    }
  
    public static void main(String[] args) {
        System.out.println("Nonce v2 Example: " + generateNonceV2());
    }
}

// Example Output: 1731349200123456789  
// (Timestamp: 1731349200123, Salt: 456789)
function generateNonceV2() {
    // Get current timestamp in milliseconds (13 digits)
    const timestamp = Date.now();
  
    // Generate random salt (6 digits)
    const salt = Math.floor(100000 + Math.random() * 900000); // Range: 100000-999999
  
    // Concatenate timestamp and salt
    return `${timestamp}${salt}`;
}
console.log("Nonce v2 Example: " + generateNonceV2());

// Example Output: 1731349200123789012  
// (Timestamp: 1731349200123, Salt: 789012)
import time
import random

def generate_nonce_v2():
    # Get current timestamp in milliseconds (13 digits)
    timestamp = int(time.time() * 1000)
    
    # Generate random salt (6 digits)
    salt = random.randint(100000, 999999)  # Range: 100000-999999
    
    # Concatenate timestamp and salt
    return f"{timestamp}{salt}"
  
print("Nonce v2 Example:", generate_nonce_v2())

# Example Output: 1731349200123678901  
# (Timestamp: 1731349200123, Salt: 678901)
#include <iostream>
#include <chrono>
#include <random>
#include <string>

std::string generateNonceV2() {
    // Get current timestamp in milliseconds (13 digits)
    auto now = std::chrono::system_clock::now();
    auto timestamp = std::chrono::duration_cast<std::chrono::milliseconds>
        (now.time_since_epoch()).count();
  
    // Generate random salt (6 digits)
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> dis(100000, 999999); // Range: 100000-999999
    int salt = dis(gen);
  
    // Concatenate timestamp and salt
    return std::to_string(timestamp) + std::to_string(salt);
}

int main() {
    std::cout << "Nonce v2 Example: " << generateNonceV2() << std::endl;
    return 0;
}

// Example Output: 1731349200123456789  
// (Timestamp: 1731349200123, Salt: 456789)