> For the complete documentation index, see [llms.txt](https://openapi-docs.nagaexchange.co.id/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://openapi-docs.nagaexchange.co.id/authentication.md).

# Authentication

## Endpoint security type

Each endpoint has a security type that determines how you interact with it. API keys are passed to the REST API via the `X-CH-APIKEY` header. **API keys and secret keys are case-sensitive.**

| Security Type | Description                                              |
| ------------- | -------------------------------------------------------- |
| NONE          | Endpoint can be accessed freely.                         |
| TRADE         | Endpoint requires sending a valid API key and signature. |
| USER\_DATA    | Endpoint requires sending a valid API key and signature. |
| USER\_STREAM  | Endpoint requires sending a valid API key.               |
| MARKET\_DATA  | Endpoint requires sending a valid API key.               |

For endpoints that require signature verification, `X-CH-SIGN`, `X-CH-APIKEY`, and `X-CH-TS` must all be present in the request headers.

{% hint style="info" %}
The `apiKey` and `secretKey` values shown in the examples on this page are illustrative placeholders. Obtain your real API key and secret key from the API management section of the NagaExchange platform.
{% endhint %}

***

## Signed (TRADE and USER\_DATA) endpoint security

* When calling a `TRADE` or `USER_DATA` endpoint, the signature must be passed in the `X-CH-SIGN` header.
* The signature algorithm is **HMAC SHA256**. The API secret corresponding to your API key is used as the HMAC SHA256 key.
* The string to sign is built by concatenating, in order: `timestamp` + `method` + `requestPath` + `body string`.
* `timestamp` must match the value sent in `X-CH-TS`. `method` is the HTTP method in uppercase (`GET`/`POST`). `requestPath` is the request path only, e.g. `/sapi/v1/order`. `body` is the raw request body string (POST only — omitted for GET).
* The signature comparison is not case-sensitive.

{% hint style="warning" %}
**GET requests with query parameters** (e.g. Query Order, Current Open Orders, Trading records) must include the query string in the signed payload. The server appends it directly after `requestPath`, separated by `?`, before hashing: `timestamp + method + requestPath + "?" + queryString`. For a GET request with no query parameters (e.g. Account Information), this `?queryString` segment is omitted entirely, matching the walkthrough below. Signing a GET request with parameters as if it had none (i.e. leaving out the query string) will produce an invalid signature.
{% endhint %}

***

## Timing security

* The `X-CH-TS` header must carry the Unix timestamp (in milliseconds) of when the request was sent, e.g. `1528394129373`.
* An optional `recvWindow` parameter specifies how many milliseconds after `timestamp` the request remains valid. If omitted, it **defaults to 5000**.
* A request is also rejected if the server determines the client's timestamp is more than one second ahead of the server's own time.

```java
if (timestamp < (serverTime + 1000) && (serverTime - timestamp) <= recvWindow) {
  // process request
} else {
  // reject request
}
```

Networks are unreliable, and requests can take a variable amount of time to arrive. `recvWindow` lets you bound how stale a request is allowed to be before the server rejects it rather than executing it late. **A `recvWindow` of 5000 or less is recommended.**

***

## Signed endpoint walkthrough — `POST /sapi/v1/order`

The following is a step-by-step example of producing a valid signed payload from the Linux command line using `echo`, `openssl`, and `curl`.

| Key       | Value                              |
| --------- | ---------------------------------- |
| apiKey    | `vmPUZE6mv9SD5V5e14y7Ju91duEh8A`   |
| secretKey | `902ae3cb34ecee2779aa4d3e1d226686` |

| Parameter | Value   |
| --------- | ------- |
| symbol    | BTCUSDT |
| side      | BUY     |
| type      | LIMIT   |
| volume    | 1       |
| price     | 9300    |

**Request body:**

```java
{"symbol":"BTCUSDT","price":"9300","volume":"1","side":"BUY","type":"LIMIT"}
```

**HMAC SHA256 signature:**

The string to sign is `timestamp + method + requestPath + body`, matching this walkthrough's endpoint (`POST /sapi/v1/order`):

```bash
[linux]$ echo -n "1588591856950POST/sapi/v1/order{\"symbol\":\"BTCUSDT\",\"price\":\"9300\",\"volume\":\"1\",\"side\":\"BUY\",\"type\":\"LIMIT\"}" | openssl dgst -sha256 -hmac "902ae3cb34ecee2779aa4d3e1d226686"
(stdin)= 32cdaa73fdb77c29fd88a4b09b47920555cb593ea0b19e28655fb97623b63091
```

**curl command:**

```bash
[linux]$ curl -X POST "https://openapi.nagaexchange.co.id/sapi/v1/order" \
  -H "Content-Type: application/json" \
  -H "X-CH-APIKEY: vmPUZE6mv9SD5V5e14y7Ju91duEh8A" \
  -H "X-CH-TS: 1588591856950" \
  -H "X-CH-SIGN: 32cdaa73fdb77c29fd88a4b09b47920555cb593ea0b19e28655fb97623b63091" \
  -d "{\"symbol\":\"BTCUSDT\",\"price\":\"9300\",\"volume\":\"1\",\"side\":\"BUY\",\"type\":\"LIMIT\"}"
```

{% hint style="info" %}
The API key and secret key shown above are illustrative placeholders, not real credentials. You can re-run the `openssl` command yourself to verify it produces the same `X-CH-SIGN` value used in the `curl` command.
{% endhint %}

***

## Signed endpoint walkthrough — `GET /sapi/v1/order` (query parameters)

Signed `GET` endpoints that take query parameters (Query Order, Current Open Orders, Trading records) sign the query string as part of the payload — there is no separate request body. Using the same illustrative `apiKey`/`secretKey` as above:

| Parameter | Value   |
| --------- | ------- |
| orderId   | 1       |
| symbol    | ethusdt |

**Query string:** `orderId=1&symbol=ethusdt`

**HMAC SHA256 signature:**

The string to sign is `timestamp + method + requestPath + "?" + queryString` (no body for GET):

```bash
[linux]$ echo -n "1588591856950GET/sapi/v1/order?orderId=1&symbol=ethusdt" | openssl dgst -sha256 -hmac "902ae3cb34ecee2779aa4d3e1d226686"
(stdin)= cc9784f85b6b786ef187f015c6e07cbcb8e2f67dd2619a01e850556440832360
```

**curl command:**

```bash
[linux]$ curl -X GET "https://openapi.nagaexchange.co.id/sapi/v1/order?orderId=1&symbol=ethusdt" \
  -H "X-CH-APIKEY: vmPUZE6mv9SD5V5e14y7Ju91duEh8A" \
  -H "X-CH-TS: 1588591856950" \
  -H "X-CH-SIGN: cc9784f85b6b786ef187f015c6e07cbcb8e2f67dd2619a01e850556440832360"
```

{% hint style="warning" %}
For a signed `GET` endpoint with **no** query parameters (e.g. Account Information), omit the `?queryString` segment entirely — the string to sign is just `timestamp + method + requestPath`.
{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://openapi-docs.nagaexchange.co.id/authentication.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
