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

# OAuth Integration

If your application acts on behalf of other users, use OAuth so each user authenticates with NinjaTrader directly instead of handing their credentials to your app. This page covers the authorization-code flow: the user approves your app, you receive a single-use code, and you exchange that code for an access token.

A complete, runnable Node/Express version of this flow is in the [OAuth example project](https://github.com/tradovate/example-api-oauth).

## Prerequisites

* A `client_id` and `client_secret` issued by NinjaTrader for your application.
* A **redirect URI** you control, registered with your credentials. NinjaTrader returns the user to this URI with the authorization code after they authenticate.

Keep your `client_secret` out of public access — store it in an environment variable or secret manager, not in client-side code or a public repository.

## The Flow

OAuth authentication is a three-step process:

1. Redirect the user to the authorize URL.
2. Receive a single-use code at your redirect URI.
3. Exchange the code for an access token.

### Step 1 — Redirect to the Authorize URL

Send the user to the authorize endpoint with `response_type=code`, your `client_id`, and your `redirect_uri`:

```js
const AUTH_URL = 'https://trader.tradovate.com/oauth'

const authUrl =
    AUTH_URL +
    '?response_type=code' +
    `&client_id=${encodeURIComponent(CLIENT_ID)}` +
    `&redirect_uri=${encodeURIComponent(REDIRECT_URI)}`

// e.g. in Express, redirect the user's browser there:
app.get('/auth', (_, res) => res.redirect(authUrl))
```

The user sees the NinjaTrader login screen and approves your application.

For the Demo environment, use `https://trader-d.tradovate.com/oauth`.

### Step 2 — Receive the Code

After the user authenticates, NinjaTrader redirects to your `redirect_uri` with a single-use `code` in the query string. Extract it:

```js
app.get('/oauth/tradovate/callback', async (req, res) => {
    if (req.query.code) {
        const code = req.query.code
        // exchange the code for a token (Step 3)
    }
})
```

### Step 3 — Exchange the Code for an Access Token

Send a form-encoded `POST` to the token endpoint with `grant_type=authorization_code` and the same `redirect_uri` you used in Step 1:

```js
const EXCHANGE_URL = 'https://live.tradovateapi.com/auth/oauthtoken'

const form = {
    grant_type: 'authorization_code',
    client_id: CLIENT_ID,
    client_secret: CLIENT_SECRET,
    redirect_uri: REDIRECT_URI,
    code: req.query.code
}

const response = await fetch(EXCHANGE_URL, {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: new URLSearchParams(form)
})

const data = await response.json()
// success: { access_token, expires_in, ... }
// failure: { error, error_description }
```

For the Demo environment, exchange the code at `https://live-api-d.tradovate.com/auth/oauthtoken`.

A successful response includes an `access_token` and `expires_in` (the token's lifetime in seconds). On failure, the response includes `error` and `error_description`.

## Using the Token

Send the access token on each request using the `Bearer` scheme — for example, to read the authenticated user with `me`:

```js
const me = await fetch('https://live.tradovateapi.com/v1/auth/me', {
    headers: { 'Authorization': `Bearer ${accessToken}` }
}).then(res => res.json())
```

The token is valid for the `expires_in` window. When it expires, run the flow again to obtain a new one. For session limits and token renewal on the credential flow, see [Authentication & Access](/api/authentication).

Other grant types (such as `client_credentials` and `jwt-bearer`) exist for server-to-server and Connect integrations. They're documented in the Connect docs, not here.