> 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/concepts/authentication.md).

# Authentication

*VNX private endpoints use ECDSA (SHA256) key-pair signing: every non read-only **`/private/*`** request requires three headers built from a signature over the request.*

## Overview

The VNX API authenticates private requests with an ECDSA key pair rather than tokens or passwords. You generate the key pair in the VNX account portal at [my.vnx.io](https://my.vnx.io); VNX stores the public key, and you keep the private key. Each non read-only request to a `/private/*` endpoint is signed locally with your private key, and VNX verifies the signature against your stored public key. There is no token exchange and nothing to refresh.

Public `GET` endpoints (`/`, `/client/assets`, `/client/tradingPairs`, `/client/quotes`) need no signing — only a `x-app-public-key` header, which is required on **all** requests.

## Key benefits

* **No shared secret in transit** — only the public key and a signature travel over the wire; the private key never leaves your environment.
* **Replay-resistant** — a monotonic nonce on every request means a captured request cannot be replayed.
* **Stateless** — no token endpoint, no expiry, no refresh; sign each request as you send it.

## The three headers

Every `/private/*` request carries:

| Header              | Value                                                           |
| ------------------- | --------------------------------------------------------------- |
| `x-app-public-key`  | Your public key from [my.vnx.io](https://my.vnx.io)             |
| `x-app-nonce`       | An always-increasing `uint64` (UNIX milliseconds recommended)   |
| `x-app-signed-data` | base64url of the ECDSA-SHA256 signature over the signing string |

`User-Agent` is also required on every request, public or private.

## How it works

The signing string is the concatenation of three parts:

```
URI path  +  canonical-JSON POST data  +  nonce
```

1. **URI path** — the request path, e.g. `/api/v1/private/accountBalance`.
2. **Canonical JSON of the POST data** — recursively sort all object keys lexicographically; arrays keep their original order. An empty body produces an empty/`{}` payload.
3. **Nonce** — the same value sent in `x-app-nonce`.

Sign that string with ECDSA over SHA256 using your private key, then base64url-encode the signature into `x-app-signed-data`.

```http
POST /api/v1/private/accountBalance HTTP/1.1 Host: api.vnx.io Content-Type: application/x-www-form-urlencoded User-Agent: MyClient/1.0 x-app-public-key: <public_key> x-app-nonce: 1708881600000 x-app-signed-data: <base64url_signature> (empty body)
```

VNX recomputes the signing string from the path, the canonicalized body, and the received nonce, then verifies the signature against your stored public key.

## Canonical JSON

Canonicalization must be deterministic so client and server produce the same bytes:

* Recursively sort object keys in lexicographic order.
* Leave arrays in their original order.
* Apply the same rules at every nesting level.

Build the canonical form first, then sign it; sign the exact bytes you transmit.

## Nonce rules

* `x-app-nonce` is an **always-increasing** `uint64`.
* Use UNIX time in **milliseconds** (recommended) so values rise naturally.
* It must **never** be reset to a lower value — VNX rejects any request whose nonce is not greater than the last one seen for that public key.

## Content types

* `application/x-www-form-urlencoded` for most `/private/*` endpoints.
* `application/json` only for `/private/addPaymentRail`.

## Security expectations

* Store the private key in a secret manager; never commit it to source code repo.
* Generate a separate key pair per environment (test vs production).
* Treat a `401`/signature failure as terminal: fix the signing string, nonce, or key before retrying.

## Related

* [Prerequisites](/vnx-global/developer/quickstart/prerequisites.md)
* [Nonce and Retries](/vnx-global/developer/nonce-and-retries.md)
* [Auth](/vnx-global/developer/api/auth.md)
* [Glossary](/vnx-global/glossary.md)
