> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://partner.ninjatrader.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://partner.ninjatrader.com/_mcp/server.

# Stage 1: Authentication

Authentication is the foundation of all API interactions with the Tradovate API. This stage ensures your integration can properly authenticate and maintain secure access to the platform.

## Overview

The authentication stage validates that your application can:

* Request access tokens using valid credentials
* Renew access tokens to maintain active sessions
* Handle authentication errors gracefully

Before you begin, review the [Rate Limits](/partner-api/core-concepts/rate-limits).

## Required Tests

### 1. Access Token Request

**Endpoint:** `POST /auth/accesstokenrequest`

### Response (200)

```json
{
  "errorText": "string",
  "hibpHint": "EmailAndPasswordCompromised",
  "accessToken": "string",
  "expirationTime": "2024-01-15T09:30:00Z",
  "passwordExpirationTime": "2024-01-15T09:30:00Z",
  "userStatus": "Active",
  "userId": 1,
  "name": "string",
  "hasLive": true,
  "hasSimPlus": true,
  "showKIDs": true
}
```

**Purpose:** Obtain an access token for API authentication.

**Test Steps:**

1. Send a POST request to `/auth/accesstokenrequest` with valid credentials
2. Verify the response contains a valid access token
3. Verify the response includes an expiration time
4. Test with invalid credentials to ensure proper error handling

**Example Request:**

```javascript
const response = await fetch('https://demo.tradovateapi.com/v1/auth/accesstokenrequest', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json'
    },
    body: JSON.stringify({
        name: 'your_username',
        password: 'your_password',
        appId: 'your_app_id',
        appVersion: '1.0.0',
        cid: 'your_cid',
        sec: 'your_sec'
    })
});

const data = await response.json();
```

**Expected Response:**

```json
{
    "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "expirationTime": "2024-01-01T12:00:00.000Z"
}
```

**Validation Criteria:**

* ✅ Access token is returned and non-empty
* ✅ Expiration time is included and valid
* ✅ Response time is under 2 seconds
* ✅ Invalid credentials return appropriate error (401 Unauthorized)

### 2. Access Token Renewal

**Endpoint:** `GET /auth/renewaccesstoken`

### Response (200)

```json
{
  "errorText": "string",
  "hibpHint": "EmailAndPasswordCompromised",
  "accessToken": "string",
  "expirationTime": "2024-01-15T09:30:00Z",
  "passwordExpirationTime": "2024-01-15T09:30:00Z",
  "userStatus": "Active",
  "userId": 1,
  "name": "string",
  "hasLive": true,
  "hasSimPlus": true,
  "showKIDs": true
}
```

**Purpose:** Extend an existing access token without creating a new session.

**Test Steps:**

1. Obtain a valid access token using `/auth/accesstokenrequest`
2. Use the access token to call `/auth/renewaccesstoken` before expiration
3. Verify the response contains a new access token
4. Verify the new token has an extended expiration time
5. Test with an expired token to ensure proper error handling

**Example Request:**

```javascript
const response = await fetch('https://demo.tradovateapi.com/v1/auth/renewaccesstoken', {
    method: 'GET',
    headers: {
        'Authorization': `Bearer ${accessToken}`,
        'Accept': 'application/json'
    }
});

const data = await response.json();
```

**Expected Response:**

```json
{
    "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "expirationTime": "2024-01-01T18:00:00.000Z"
}
```

**Validation Criteria:**

* ✅ New access token is returned and different from original
* ✅ New expiration time is extended beyond original
* ✅ Response time is under 1 second
* ✅ Expired tokens return appropriate error (401 Unauthorized)

## Error Handling

Your implementation must handle the following error scenarios:

### Common Error Responses

**Invalid Credentials (401):**

```json
{
    "error": "Invalid credentials",
    "message": "The provided username or password is incorrect"
}
```

**Token Expired (401):**

```json
{
    "error": "Token expired",
    "message": "The access token has expired and cannot be renewed"
}
```

**Rate Limiting (429):**

```json
{
    "error": "Rate limit exceeded",
    "message": "Too many requests. Please try again later."
}
```

## Best Practices

1. **Token Storage**: Store access tokens securely and never log them
2. **Token Refresh**: Implement automatic token renewal before expiration
3. **Error Handling**: Implement retry logic with exponential backoff
4. **Monitoring**: Log authentication failures for debugging
5. **Session Management**
   * Should use a single access token across all API powered services.
   * Should prefer using the `/auth/renewaccesstoken` endpoint to renew the token instead of requesting a new one.
   * Should request a new token only if the previous one has expired and renewal fails.

## Testing Checklist

* [ ] Access token request succeeds with valid Credentials
* [ ] If implementing retry logic, don't retry on the case `401: Invalid Credentials`
* [ ] Access token renewal succeeds with valid token
* [ ] Access token renewal fails with expired token
* [ ] Response times meet performance requirements
* [ ] Error responses are properly handled
* [ ] Session management is properly implemented

## Next Steps

After completing Stage 1 authentication tests, proceed to [Stage 2: Websocket Management](/overview/conformance-testing/stage-2-websocket-management).