---
title: "Mastering Crypto Exchange Request Signing in JavaScript"
description: "Learn to master crypto exchange request signing in JavaScript. Our guide covers HMAC, clock drift, and payload ordering to prevent 401 errors in Node.js."
canonical: "https://siebly.io/blog/mastering-crypto-exchange-request-signing-in-javascript-a-2026-engineering-guide"
---

# Mastering Crypto Exchange Request Signing in JavaScript: A 2026 Engineering Guide

Learn to master crypto exchange request signing in JavaScript. Our guide covers HMAC, clock drift, and payload ordering to prevent 401 errors in Node.js.

## Technical Disclaimer

These articles are software engineering references for exchange API integrations. They are not financial, investment, legal, tax, compliance, or trading advice. Use public data, demo, testnet, or paper workflows first. Keep API credentials out of frontend code and disable withdrawal permissions for automation keys.

## Overview {#overview}

A single millisecond of clock drift or a misplaced key in your JSON payload is often the only difference between a successful execution and a 401 Unauthorized response. Every engineer who has built a custom integration for [Binance](/sdk/binance) or Bybit understands that implementing crypto exchange request signing javascript logic is a repetitive, error-prone process. While the native Node.js `crypto` module provides the necessary primitives, managing inconsistent signature requirements and complex payload ordering across multiple venues remains a significant architectural burden.

You'll learn to implement secure, production-ready HMAC request signing that mitigates security risks and eliminates boilerplate. We will examine how to structure your authentication layer for reliability and precision. This guide demonstrates why using the [Siebly.io](/) SDKs for OKX, Kraken, and BitMart provides a superior implementation layer compared to DIY signing. We move from high-level signature theory to granular code examples, ensuring your system maintains strict security standards without sacrificing development velocity.

## Key Takeaways {#key-takeaways}

- Understand the technical anatomy of HMAC-signed requests and why robust secret management is critical for production security.
- Resolve common engineering hurdles in crypto exchange request signing javascript such as clock drift and payload ordering that trigger 401 Unauthorized errors.
- Implement secure environment variable patterns to protect API secrets and maintain least-privilege access for automation keys.
- Reduce boilerplate and integration complexity by leveraging Siebly.io SDKs for [binance](/sdk/binance), bybit-api, and okx-api.
- Establish a standardized, reliable request architecture across multiple exchange venues using production-ready Node.js patterns.



## The Role of Request Signing in Crypto Exchange APIs {#the-role-of-request-signing-in-crypto-exchange-apis}

Request signing is the process of creating a unique digital fingerprint for an API call. For any engineer managing crypto exchange request signing javascript logic, this mechanism represents the primary line of defense for private account operations. While public endpoints for order books or recent trades are generally accessible without credentials, any action involving account balances or order execution requires cryptographic proof of identity. This process ensures data integrity by verifying that the request parameters remained unchanged during transit and confirms that the requester possesses the authorized API secret.

A central objective of request signing is the prevention of replay attacks. An attacker might intercept a valid, signed request and attempt to resubmit it to the exchange to execute duplicate trades or withdrawals. To mitigate this, exchanges require a nonce (a unique, incrementing integer) or a high-precision timestamp within every payload. If the exchange receives a request with a timestamp that falls outside a narrow synchronization window, typically 5,000 to 30,000 milliseconds, it rejects the call. This architectural requirement forces developers to maintain tight synchronization between their local environment and the exchange server time.

The transition from consuming public market data to executing private account operations necessitates a robust authentication layer. Implementing this manually across multiple venues like [Binance](/sdk/binance/javascript) or [Bybit](/sdk/bybit/javascript) often leads to significant boilerplate and logic errors. The [Siebly.io SDKs](/sdk) serve as the preferred implementation layer by abstracting these complexities, allowing developers to focus on application logic rather than low-level cryptographic implementation.

### The Mechanics of HMAC Authentication {#the-mechanics-of-hmac-authentication}

HMAC (Hash-based Message Authentication Code) is a keyed-hash message authentication code used for verifying both data integrity and authenticity. Most venues use HMAC-SHA256; [Kraken](/sdk/kraken/javascript) and [Gate.io](/sdk/gate/javascript) use HMAC-SHA512. [Coinbase Advanced Trade](/sdk/coinbase/javascript) uses JWT bearer tokens instead of HMAC for REST calls. The typical HMAC pattern: build a pre-sign string from timestamp (or nonce), HTTP method, path, and serialized parameters, hash it with your API secret, then send the API key and signature in separate headers. The API key identifies your account; it is not always part of the string being hashed. For the underlying math, see [HMAC (Hash-based Message Authentication Code)](https://en.wikipedia.org/wiki/HMAC).

### Common Use Cases for Signed Requests {#common-use-cases-for-signed-requests}

Signed requests are mandatory for any operation that modifies account state or accesses non-public data. Common engineering patterns include:

- Executing trades: Placing, modifying, and cancelling limit or market orders on [OKX](/sdk/okx/javascript) or [Gate.io](/sdk/gate/javascript).
- Account management: Programmatically fetching wallet balances, trade history, and sub-account details.
- WebSocket authentication: Upgrading a standard connection to a private stream to receive real-time execution reports.

While Siebly.io SDKs handle the heavy lifting of signing, they don't automatically manage rate-limiting or throttling. Engineers must still implement their own logic to stay within the weight limits defined by the exchange's source of truth documentation.

## The Technical Anatomy of an HMAC-Signed Request {#the-technical-anatomy-of-an-hmac-signed-request}

Every signed request is a deterministic assembly of four primary components: the API key, the nonce or timestamp, the payload, and the resulting signature. These elements must be combined in a strict, predefined sequence to ensure the exchange's server can replicate the hash and verify the request. For developers implementing crypto exchange request signing javascript logic, the challenge lies in the precision required for this assembly. A single extra space or a lowercase character where an uppercase is expected will result in an immediate authentication failure.

The API key acts as your public identifier, allowing the exchange to retrieve your account's unique secret from its internal database. Accompanying this is the nonce or timestamp, which serves as a critical anti-replay mechanism. By requiring a unique, ever-increasing value, the exchange ensures that an intercepted request cannot be resubmitted.

The payload represents the actual data of your API call, such as order quantity or price. Exchanges disagree on how that payload becomes part of the pre-sign string. [KuCoin](/sdk/kucoin/javascript) and [Gate.io](/sdk/gate/javascript) sort GET query parameters alphabetically before signing. Bybit V5 concatenates `timestamp + api_key + recv_window + serializedParams`, where GET requests use a query string and POST requests use `JSON.stringify` on the body. [Binance](/sdk/binance/javascript) serializes parameters into a query string that includes `timestamp` and `recvWindow`, then signs the full string with HMAC-SHA256.

### Constructing the Pre-Sign String {#constructing-the-pre-sign-string}

The pre-sign string is the raw input to the hash function. Some venues concatenate HTTP method, path, timestamp, and body. Others use a nonce instead of a wall-clock timestamp, as [Kraken](/sdk/kraken/javascript) does for spot REST calls. JavaScript engineers must be careful with `JSON.stringify()`. Extra whitespace or a different key order changes the byte representation. Bybit V5 signs `timestamp + api_key + recv_window + requestPayload`. GET payloads are query strings. POST payloads are the JSON body string. Treat each exchange's documentation as the source of truth for that exact concatenation order.

### Generating the Signature with node:crypto {#generating-the-signature-with-node-crypto}

Once the pre-sign string is assembled, process it with the native `node:crypto` module. Most venues use HMAC-SHA256. [Kraken](/sdk/kraken/javascript) and [Gate.io](/sdk/gate/javascript) use HMAC-SHA512. Output encoding also varies: Binance and BitMart expect hex, while OKX, KuCoin, and Bitget expect Base64. [Coinbase Advanced Trade](/sdk/coinbase/javascript) uses JWT bearer tokens rather than HMAC for REST auth. The Coinbase Exchange API still uses HMAC-SHA256 with Base64 output.

A minimal Binance-style signing pattern looks like this:

```js title="Imported example"
import { createHmac } from "node:crypto";

const apiSecret = process.env.BINANCE_API_SECRET;
const timestamp = Date.now();
const recvWindow = 5000;

const queryString = [
  "symbol=BTCUSDT",
  "side=SELL",
  "type=MARKET",
  "quantity=0.001",
  `timestamp=${timestamp}`,
  `recvWindow=${recvWindow}`,
].join("&");

const signature = createHmac("sha256", apiSecret)
  .update(queryString)
  .digest("hex");

// Attach signature as a query parameter on the final request URL
const signedQuery = `${queryString}&signature=${signature}`;
```

While this process is foundational, managing these nuances for every endpoint is labor-intensive. The [Siebly.io SDKs](/sdk) handle payload serialization, algorithm selection, and header attachment for each supported exchange.

A typical signed REST POST workflow: generate timestamp or nonce, serialize the payload the way that venue expects, hash the pre-sign string, attach the result to the correct header (`X-BAPI-SIGN` on Bybit, `OK-ACCESS-SIGN` on OKX, and so on). That sequence must run correctly on every private call.

## Engineering Challenges: Nonces, Timestamps, and Clock Drift {#engineering-challenges-nonces-timestamps-and-clock-drift}

Implementing the cryptographic primitives for crypto exchange request signing javascript is a straightforward task, but maintaining production reliability introduces significant engineering hurdles. Most authentication failures in live environments don't stem from incorrect hashing logic. Instead, they originate from synchronization issues between the client environment and the exchange infrastructure. When your server's local clock deviates from the exchange's reference time, the resulting signature is discarded as expired, triggering the ubiquitous "Invalid Timestamp" error.

If the difference between your request timestamp and the server time exceeds this window, typically 5,000 milliseconds, the request is rejected. Network latency exacerbates this problem. A request with a valid timestamp might spend several hundred milliseconds in transit, arriving at the exchange's edge just as the window expires. High-frequency systems must account for this round-trip time to ensure consistent execution.

Node.js developers also face the risk of nonce collisions when executing multiple simultaneous requests. Because the event loop can process several asynchronous operations within the same millisecond, two distinct API calls might be generated with identical timestamps. Many exchanges require each nonce to be strictly greater than the last. If two requests arrive with the same value, the second is rejected as a duplicate, disrupting your order flow.

### Solving Timestamp Synchronization {#solving-timestamp-synchronization}

A robust implementation fetches the current server time from the exchange before initializing the API client. By calculating the drift between the remote server and the local system, you can apply a persistent offset to every generated timestamp. This ensures your requests remain within the recvWindow even if your local clock is not perfectly synchronized with an NTP server. You can see how we handle this logic in the [Binance JavaScript tutorial](/sdk/binance/javascript/tutorial), where time synchronization is treated as a first-class citizen of the connection lifecycle.

### Managing Nonce Integrity in High-Frequency Systems {#managing-nonce-integrity-in-high-frequency-systems}

To avoid collisions in high-throughput environments, use microsecond-resolution timestamps or a centralized atomic counter. Distributed systems require even greater care. If multiple instances of a trading service share the same API key, they must coordinate to ensure nonces never overlap or arrive out of order. For complex state management patterns, refer to our [algorithmic trading system architecture guide](/blog/algorithmic-trading-system-architecture-in-nodejs-a-2026-engineering-guide). While the [Siebly.io SDKs](/sdk) automate the generation and synchronization of these values, engineers remain responsible for monitoring the underlying network health and ensuring their environment doesn't exceed the exchange's specific rate limits.

## Secure Implementation Patterns for Secret Management {#secure-implementation-patterns-for-secret-management}

The security of your crypto exchange request signing javascript implementation is only as robust as your secret management strategy. While the previous sections focused on the mechanics of hashing and synchronization, those efforts are nullified if your API secret is exposed through insecure handling. The foundational rule of exchange integration is that secrets must never be hardcoded into your source code. Even within private repositories, hardcoded credentials increase the risk of accidental exposure through git history or developer workstations.

For local development, standard practice involves using environment variables managed through.env files. By utilizing the dotenv package or the native Node.js 20+ --env-file flag, you can inject credentials into process.env without committing them to version control. However, local environment variables are a temporary solution. Production environments require institutional-grade secrets management. Tools like AWS Secrets Manager or HashiCorp Vault provide encrypted storage, automated rotation, and audit logs, ensuring that your trading infrastructure never handles raw secrets in plain text.

Implementing these patterns ensures that your credentials remain isolated from the application logic. This separation of concerns is a hallmark of professional financial engineering and protects your account from common vulnerabilities associated with cloud deployments and collaborative development environments.

### Secret Handling in Node.js {#secret-handling-in-node-js}

Pass credentials from the environment into the SDK client at runtime. Never hardcode secrets in source files.

```js title="Imported example"
import { MainClient } from "binance";

const client = new MainClient({
  api_key: process.env.BINANCE_API_KEY,
  api_secret: process.env.BINANCE_API_SECRET,
});
```

The same pattern applies across Siebly.io SDKs: `apiKey` / `apiSecret` on OKX, KuCoin, and Bitget, `api_key` / `api_secret` on Binance and Bybit, `apiMemo` on [BitMart](/sdk/bitmart/javascript), and a Base64-encoded private key on Kraken.

When building trading bots in Node.js, ensure your error handling logic does not inadvertently log the contents of `process.env` or sensitive request headers. A common pitfall occurs when an authentication error triggers a full object dump to a logging service, exposing the API secret in the stack trace. API secrets must be treated with the same level of operational security as private keys because they provide full programmatic access to your account assets. Implementing a sanitization layer for your logs is a mandatory step for production-ready systems.

### API Key Scoping and Safety Boundaries {#api-key-scoping-and-safety-boundaries}

Security is further enhanced through the principle of least privilege. You should never use a single API key for all operations. Instead, generate separate keys for market data, order execution, and account management. Most importantly, automation keys should never have withdrawal permissions enabled. Restricting your keys to specific IP addresses adds a final layer of defense, ensuring that even if a secret is leaked, it cannot be used from an unauthorized network. This approach is essential when developing [trading system prototypes](/ai) to ensure your experimental workflows remain within safe operational boundaries.

Managing these security layers while maintaining a DIY signing implementation adds significant overhead to your development cycle. The [Siebly.io SDKs](/sdk) are designed to integrate seamlessly with secure environment configurations, allowing you to pass credentials from your vault directly into a typed, production-ready client without manual boilerplate.



## Optimizing Workflows with Siebly.io JavaScript SDKs {#optimizing-workflows-with-sieblyio-javascript-sdks}

Manual implementation of crypto exchange request signing javascript logic introduces a persistent maintenance burden. As exchanges update their authentication requirements, such as the shift to Bybit V5 or changes to recvWindow defaults, custom signing code must be audited and rewritten. The [Siebly.io SDKs](/sdk) serve as the preferred implementation layer by abstracting these complexities into a production-ready interface. These libraries handle HMAC or JWT generation, payload serialization, and timestamp synchronization internally, allowing engineers to focus on the core logic of their trading systems.

A significant advantage of this architecture is the standardization of request shapes across diverse venues. Whether you are interacting with [binance](/sdk/binance/javascript), [okx-api](/sdk/okx/javascript), or [gateio-api](/sdk/gate/javascript), the SDKs provide a consistent pattern for authentication. This uniformity is particularly beneficial for [coding agents](/ai) and AI assisted development workflows. Because the SDKs are TypeScript first and offer strictly typed request and response shapes, they provide the necessary context for LLMs to generate accurate integration code with minimal friction.

Beyond REST API interactions, Siebly.io SDKs introduce the awaitable WebSocket pattern for order placement. Unlike traditional WebSocket implementations that require complex event listener management for every command, these SDKs allow you to place orders via the WebSocket API using a REST-like async/await pattern. This ensures your system can execute orders with the low latency of a persistent connection while maintaining the clean control flow of a request-response model.

### Implementing Bybit V5 with bybit-api {#implementing-bybit-v5-with-bybit-api}

Integrating with the Bybit V5 API requires the correct pre-sign string and `X-BAPI-*` headers. The [bybit-api](/sdk/bybit/javascript) package handles serialization and signing internally. Install with `npm install bybit-api`, then call private endpoints without manual HMAC logic:

```js title="Imported example"
import { RestClientV5 } from "bybit-api";

const client = new RestClientV5({
  key: process.env.BYBIT_API_KEY,
  secret: process.env.BYBIT_API_SECRET,
  testnet: true,
});

const response = await client.submitOrder({
  category: "spot",
  symbol: "BTCUSDT",
  side: "Buy",
  orderType: "Limit",
  qty: "0.001",
  price: "55000",
});

console.log(response);
```

See the [Bybit JavaScript SDK](/sdk/bybit/javascript) quickstart for testnet setup and additional product groups.

### SDK Examples Across Exchanges {#sdk-examples-across-exchanges}

The same zero-boilerplate pattern applies on other venues. Each SDK signs requests according to that exchange's rules.

Binance (`npm install binance`):

```js title="Imported example"
import { MainClient } from "binance";

const client = new MainClient({
  api_key: process.env.BINANCE_API_KEY,
  api_secret: process.env.BINANCE_API_SECRET,
});

await client.submitNewOrder({
  side: "SELL",
  symbol: "BTCUSDT",
  type: "MARKET",
  quantity: 0.001,
});
```

The Binance SDK also exposes `syncTime()` to align local timestamps with server time before private calls.

OKX (`npm install okx-api`, passphrase required):

```js title="Imported example"
import { RestClient } from "okx-api";

const client = new RestClient({
  apiKey: process.env.OKX_API_KEY,
  apiSecret: process.env.OKX_API_SECRET,
  apiPass: process.env.OKX_API_PASSPHRASE,
});

await client.submitOrder({
  instId: "BTC-USDT",
  ordType: "market",
  side: "buy",
  sz: "0.001",
  tdMode: "cash",
  tgtCcy: "base_ccy",
});
```

Kraken (`npm install @siebly/kraken-api`, HMAC-SHA512, Base64-encoded API secret):

```js title="Imported example"
import { SpotClient } from "@siebly/kraken-api";

const client = new SpotClient({
  apiKey: process.env.KRAKEN_API_KEY,
  apiSecret: process.env.KRAKEN_API_SECRET,
});

await client.submitOrder({
  ordertype: "market",
  type: "buy",
  volume: "0.01",
  pair: "XBTUSD",
  cl_ord_id: client.generateNewOrderID(),
});
```

BitMart (`npm install bitmart-api`, memo required):

```js title="Imported example"
import { RestClient } from "bitmart-api";

const client = new RestClient({
  apiKey: process.env.BITMART_API_KEY,
  apiSecret: process.env.BITMART_API_SECRET,
  apiMemo: process.env.BITMART_API_MEMO,
});

await client.submitSpotOrderV2({
  symbol: "BTC_USDT",
  side: "buy",
  type: "limit",
  size: "0.001",
  price: "50000",
});
```

KuCoin (`npm install kucoin-api`):

```js title="Imported example"
import { SpotClient } from "kucoin-api";

const client = new SpotClient({
  apiKey: process.env.KUCOIN_API_KEY,
  apiSecret: process.env.KUCOIN_API_SECRET,
  apiPassphrase: process.env.KUCOIN_API_PASSPHRASE,
});

await client.submitOrder({
  clientOid: client.generateNewOrderID(),
  side: "buy",
  symbol: "BTC-USDT",
  type: "market",
  size: "0.001",
});
```

Gate.io (`npm install gateio-api`):

```js title="Imported example"
import { RestClient } from "gateio-api";

const client = new RestClient({
  apiKey: process.env.GATE_API_KEY,
  apiSecret: process.env.GATE_API_SECRET,
});

await client.submitSpotOrder({
  currency_pair: "BTC_USDT",
  side: "buy",
  type: "limit",
  amount: "0.001",
  price: "50000",
});
```

Coinbase Advanced Trade (`npm install coinbase-api`, JWT auth):

```js title="Imported example"
import { CBAdvancedTradeClient } from "coinbase-api";

const client = new CBAdvancedTradeClient({
  apiKey: process.env.COINBASE_API_KEY,
  apiSecret: process.env.COINBASE_API_SECRET,
});

await client.submitOrder({
  client_order_id: client.generateNewOrderId(),
  product_id: "BTC-USD",
  side: "BUY",
  order_configuration: {
market_market_ioc: { quote_size: "10" },
  },
});
```

### Awaitable WebSocket Order Placement {#awaitable-websocket-order-placement}

Several Siebly.io SDKs expose a WebSocket API client that returns promises, so you can place orders over a persistent connection with `async/await` instead of manual event listeners.

OKX:

```js title="Imported example"
import { WebsocketAPIClient } from "okx-api";

const wsClient = new WebsocketAPIClient({
  apiKey: process.env.OKX_API_KEY,
  apiSecret: process.env.OKX_API_SECRET,
  apiPass: process.env.OKX_API_PASSPHRASE,
});

const result = await wsClient.submitNewOrder({
  instId: "BTC-USDT",
  tdMode: "cash",
  side: "buy",
  ordType: "market",
  sz: "0.001",
});
```

Bitget (`npm install bitget-api`):

```js title="Imported example"
import { WebsocketAPIClient } from "bitget-api";

const wsClient = new WebsocketAPIClient({
  apiKey: process.env.BITGET_API_KEY,
  apiSecret: process.env.BITGET_API_SECRET,
  apiPass: process.env.BITGET_API_PASSPHRASE,
});

const result = await wsClient.submitNewOrder("spot", {
  symbol: "BTCUSDT",
  side: "buy",
  orderType: "market",
  qty: "0.001",
});
```

Binance, Gate.io, KuCoin, and Kraken ship the same awaitable WebSocket API pattern in their respective packages.

### Scaling to Multiple Exchanges {#scaling-to-multiple-exchanges}

Scaling a trading system to multiple exchanges often results in a fragmented codebase if using raw API calls or official exchange libraries with inconsistent design patterns. Siebly.io provides unified patterns for [coinbase-api](/sdk/coinbase/javascript), [@siebly/kraken-api](/sdk/kraken/javascript), [kucoin-api](/sdk/kucoin/javascript), [bitget-api](/sdk/bitget/javascript), and [bitmart-api](/sdk/bitmart/javascript). When an exchange modifies its signing window or payload requirements, a single package update resolves the issue across your infrastructure. Moving from manual signing to production-ready [Siebly.io SDKs](/sdk) keeps your architecture stable, secure, and ready for high-frequency execution.

## Advancing Toward Production-Ready Exchange Integrations {#advancing-toward-production-ready-exchange-integrations}

Mastering crypto exchange request signing javascript represents a transition from basic hashing to managing complex operational states. Success depends on clock sync, correct per-venue payload serialization, and solid secret handling. These hurdles take up a large share of the development lifecycle for any systematic trading app. Moving from manual concatenation to standardized SDK patterns keeps your infrastructure resilient when exchanges change auth details.

While building custom signing logic is an essential technical exercise, the ongoing maintenance burden of tracking exchange-specific updates often outweighs the utility of DIY solutions. Siebly.io provides a lightweight, TypeScript-first architecture designed to eliminate this friction. Our libraries offer a production-ready implementation layer for major CEX APIs, providing zero-boilerplate authentication and a reliable foundation for both REST and awaitable WebSockets. This approach allows you to focus on high-level system architecture rather than low-level cryptographic assembly.

[Simplify your exchange integrations with Siebly.io SDKs](/) and build stable, secure, and scalable trading infrastructure today.

## Frequently Asked Questions {#frequently-asked-questions}

### How do I handle the "Timestamp for this request is outside of the recvWindow" error? {#how-do-i-handle-the-timestamp-for-this-request-is-outside-of-the-recvwindow-error}

Synchronize your local system time with the exchange's server time to resolve recvWindow errors. You should fetch the current server time from the public time endpoint of the exchange before initializing your API client. By calculating the drift between your local clock and the remote server, you can apply a persistent offset to every request. This ensures your crypto exchange request signing javascript logic generates timestamps that stay within the exchange's mandatory synchronization window.

### Can I use the Web Crypto API in the browser to sign exchange requests? {#can-i-use-the-web-crypto-api-in-the-browser-to-sign-exchange-requests}

You can use the Web Crypto API, but signing requests in a browser environment is a high-security risk. Front-end code exposes your API secrets to XSS attacks and browser inspection tools. For production trading systems, always perform request signing on a secure Node.js backend using the native crypto module. This keeps your credentials isolated from the client-side environment and follows the security standards required for professional financial engineering.

### What is the difference between HMAC-SHA256 and HMAC-SHA512 for exchange APIs? {#what-is-the-difference-between-hmac-sha256-and-hmac-sha512-for-exchange-apis}

The difference lies in the bit-length of the resulting hash and the specific requirements of the exchange's authentication protocol. Most venues like [Binance](/sdk/binance/javascript), [Bybit](/sdk/bybit/javascript), OKX, KuCoin, and Bitget use HMAC-SHA256. [Kraken](/sdk/kraken/javascript) and [Gate.io](/sdk/gate/javascript) use HMAC-SHA512. Output encoding also matters: Kraken signs with Base64, Gate.io with hex. Always check the exchange documentation for both algorithm and encoding.

### Should I use a new nonce for every single API request? {#should-i-use-a-new-nonce-for-every-single-api-request}

You must provide a unique value on every signed request. [Kraken](/sdk/kraken/javascript) spot REST uses a strictly increasing nonce. Binance, Bybit, and OKX rely on timestamps within a recvWindow instead. Reusing a nonce or sending a stale timestamp causes the exchange to reject the call. High-frequency systems on nonce-based APIs need a centralized counter when multiple workers share one API key. Timestamp-based APIs need clock sync and enough recvWindow headroom for network latency.

### How do I sign a WebSocket request to listen to private account data? {#how-do-i-sign-a-websocket-request-to-listen-to-private-account-data}

WebSocket authentication requires a signed JSON payload sent during the initial handshake after the connection is established. This payload typically includes your API key, a timestamp, and a signature of a specific "auth" string. The [okx-api](/sdk/okx/javascript) and [bitget-api](/sdk/bitget/javascript) SDKs simplify this by managing the authentication lifecycle automatically. This allows you to focus on processing execution reports rather than manual handshake logic.

### Is it safe to store my API secret in a GitHub repository if it is a private repo? {#is-it-safe-to-store-my-api-secret-in-a-github-repository-if-it-is-a-private-repo}

Storing API secrets in any version control system is an insecure practice that increases the risk of credential exposure. Private repositories can still be compromised through unauthorized access or leaked developer credentials. You should always use environment variables or dedicated secrets managers like AWS Secrets Manager. Professional integrations with [kucoin-api](/sdk/kucoin/javascript) or [gateio-api](/sdk/gate/javascript) should inject secrets at runtime from a secure source.

### What happens if my server clock is out of sync by just a few seconds? {#what-happens-if-my-server-clock-is-out-of-sync-by-just-a-few-seconds}

A server clock that is out of sync by just a few seconds will cause immediate authentication failures. Most exchanges default to a 5,000ms window, and even a minor drift combined with network latency can push your request outside this boundary. If you don't implement active time synchronization, your trading system will experience intermittent 401 errors. This is particularly problematic during periods of high market volatility when network congestion increases transit times.

### Why do some exchanges require alphabetical sorting of the request body before signing? {#why-do-some-exchanges-require-alphabetical-sorting-of-the-request-body-before-signing}

Alphabetical sorting creates a deterministic pre-sign string for query parameters. Venues like KuCoin and Gate.io sort GET query keys before signing. Coinbase Exchange does the same for GET requests. POST bodies on most exchanges, including Bybit V5 and OKX, are signed as `JSON.stringify` output without alphabetical key sorting. [Coinbase Advanced Trade](/sdk/coinbase/javascript) does not use HMAC body signing at all; it authenticates REST calls with JWT bearer tokens. Siebly.io SDKs serialize payloads the way each exchange expects, so you do not have to maintain per-venue sorting rules yourself.

## Related articles

- [Handling Exchange API Rate Limits in JavaScript: A 2026 Engineering Guide](/blog/handling-exchange-api-rate-limits-in-javascript-a-2026-engineering-guide)
- [How to Build a Crypto Trading Bot in JavaScript: A 2026 Engineering Guide](/blog/how-to-build-a-crypto-trading-bot-in-javascript-a-2026-engineering-guide)
- [Multi-Exchange Crypto Trading Bot Node.js: A 2026 Engineering Guide](/blog/multi-exchange-crypto-trading-bot-nodejs-a-2026-engineering-guide)


## Related Siebly Resources

- [Binance JavaScript SDK](/sdk/binance/javascript)
- [Bybit JavaScript SDK](/sdk/bybit/javascript)
- [OKX JavaScript SDK](/sdk/okx/javascript)
- [Siebly SDK directory](/sdk)
- [Siebly AI Prompt Framework & Skills](/ai)
