# Authentication

HMAC-SHA256 based authentication. Every request must include an `Authorization` header.

#### Header Format

```
Authorization: HMAC {api_key}:{signature}:{nonce}:{timestamp}
```

All four parts are separated by `:` with no spaces.

#### Parameters

| Parameter   | Type   | Description                                                                                            |
| ----------- | ------ | ------------------------------------------------------------------------------------------------------ |
| `api_key`   | String | Your API key (provided by Vagon)                                                                       |
| `signature` | String | HMAC-SHA256 **hex digest** of the signing string (see below)                                           |
| `nonce`     | String | A unique random string for each request (e.g., UUID). Must never be reused.                            |
| `timestamp` | String | Current time as **milliseconds since Unix epoch** (e.g., `1712567890123`). Not seconds — milliseconds. |

#### Signature Computation

**Step 1 — Build the signing string**

Concatenate the following values **with no separator** (no spaces, no newlines, no delimiters):

```
{api_key}{HTTP_METHOD}{path}{timestamp}{nonce}{request_body}
```

| Component      | Description                                                                   | Example                                |
| -------------- | ----------------------------------------------------------------------------- | -------------------------------------- |
| `api_key`      | Same API key used in the header                                               | `ak_live_abc123`                       |
| `HTTP_METHOD`  | Uppercase HTTP method                                                         | `POST`, `GET`, `PATCH`, `DELETE`       |
| `path`         | **Full request path** including the base path, without query string or host   | `/organization-management/v1/machines` |
| `timestamp`    | Same timestamp used in the header (milliseconds)                              | `1712567890123`                        |
| `nonce`        | Same nonce used in the header                                                 | `550e8400-e29b-41d4-a716-446655440000` |
| `request_body` | Raw JSON request body. **Empty string for GET/DELETE requests with no body.** | `{"plan_id":1,"quantity":1}`           |

**Step 2 — Sign with HMAC-SHA256**

Sign the concatenated string using your **API secret** as the key, producing a **hex digest** (lowercase).

```
signature = HMAC-SHA256(api_secret, signing_string).hexdigest
```

#### Important Notes

* **Path must be the full path** (e.g., `/organization-management/v1/machines`), without query string or host.
* **Timestamp is in milliseconds**, not seconds (13 digits, e.g., `1712567890123`).
* **GET/DELETE requests** with no body: use an empty string `""` as the `request_body` component.
* **Nonce must be unique** per request (use UUID or random string).
* **Signature is hex-encoded**: lowercase hex string (64 characters for SHA-256), not Base64.

#### Full Example

**Given:**

* API Key: `ak_live_abc123`
* API Secret: `sk_live_xyz789`
* Method: `POST`
* Path: `/organization-management/v1/machines`
* Timestamp: `1712567890123`
* Nonce: `550e8400-e29b-41d4-a716-446655440000`
* Body: `{"plan_id":1,"quantity":1,"region":"dublin"}`

**Step 1 — Signing string (concatenated, no separator):**

```
ak_live_abc123POST/organization-management/v1/machines1712567890123550e8400-e29b-41d4-a716-446655440000{"plan_id":1,"quantity":1,"region":"dublin"}
```

**Step 2 — Compute signature:**

```python
import hmac, hashlib
signing_string = 'ak_live_abc123POST/organization-management/v1/machines1712567890123550e8400-e29b-41d4-a716-446655440000{"plan_id":1,"quantity":1,"region":"dublin"}'
signature = hmac.new(b'sk_live_xyz789', signing_string.encode(), hashlib.sha256).hexdigest()
```

**Step 3 — Final header:**

```
Authorization: HMAC ak_live_abc123:{computed_signature}:550e8400-e29b-41d4-a716-446655440000:1712567890123
```

**GET request example (no body):**

```
signing_string = "ak_live_abc123GET/organization-management/v1/machines1712567890123550e8400-e29b-41d4-a716-446655440000"
```

#### Replay Protection

Requests with a timestamp older than **60 seconds** from the server's current time are rejected. Ensure your system clock is synchronized (NTP recommended).

#### Error Responses

| HTTP Status        | Cause                                                                         |
| ------------------ | ----------------------------------------------------------------------------- |
| `400 Bad Request`  | Missing `Authorization` header                                                |
| `401 Unauthorized` | Invalid signature, expired timestamp, missing token parts, or unknown API key |


---

# Agent Instructions: 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:

```
GET https://docs.vagon.io/teams/reference/authentication.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
