> For the complete documentation index, see [llms.txt](https://vnx.gitbook.io/vnx-global/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://vnx.gitbook.io/vnx-global/developer/nonce-and-retries.md).

# Nonce and Retries

*The VNX API has no **`Idempotency-Key`**; request safety comes from the monotonic nonce on every signed request plus client-supplied unique references like **`clordid`**.*

## Overview

Network blips, timeouts, and process restarts must never cause a duplicate order or transfer. VNX does not use an idempotency key. Instead, two mechanisms protect you:

* **The monotonic nonce.** Every `/private/*` request carries an always-increasing `x-app-nonce`. VNX rejects any request whose nonce is not greater than the last one it saw for your public key, so a replayed (captured) request with an old nonce is refused.
* **Client-supplied unique references.** For orders you send your own `clordid` (client order ID); reusing logic around that reference lets you detect and avoid duplicates on your side.

The API is also rate-limited to **1 request/second per public key**, and there are **no webhooks** — you confirm outcomes by polling the relevant query endpoint.

## Key benefits

* **Replay protection by default** — the nonce alone blocks captured-request replays.
* **Client-owned references** — `clordid` gives you a stable handle to reconcile orders without a server-issued key.
* **Predictable pacing** — the 1 req/sec limit makes safe retry timing simple to reason about.

## How nonce safety works

1. Each request is signed over the URI path, the canonical-JSON body, and the nonce (see Authentication).
2. The nonce must be a strictly increasing `uint64` (UNIX milliseconds recommended).
3. VNX tracks the highest nonce seen per public key and rejects anything not higher.
4. A captured request cannot be replayed: its nonce is no longer greater than the latest one.

Because the nonce changes per request, a genuine retry is a **new** request with a **fresh, higher** nonce and a fresh signature — not a byte-for-byte resend.

## Retrying safely

The rate limit is 1 request/sec per public key, so design retries around it:

* **2xx** — success; do not retry.
* **4xx (client errors)** — fix the request; do not blindly retry.
* **429 (rate limited)** — you exceeded 1 req/sec; back off and retry no faster than the limit.
* **5xx / network error before response** — retry with a **new, higher nonce** and a fresh signature, using exponential backoff with jitter while respecting 1 req/sec.

For state-changing calls where you cannot tell whether the first attempt landed (e.g. a timeout on `addOrder`), use your `clordid` to check before resending: poll `queryOrders` / `queryTrades` and only resubmit if the order is absent.

## Related

* [Authentication](/vnx-global/developer/concepts/authentication.md)
* [First API Call](/vnx-global/developer/quickstart/first-api-call.md)
* [Glossary](/vnx-global/glossary.md)
