> For the complete documentation index, see [llms.txt](https://docs.iadvize.dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.iadvize.dev/technologies/graphql-api/guides/managing-iadvize-api-access-tokens.md).

# Managing iAdvize API Access Tokens

> iAdvize access tokens are valid for **24 hours**. The authentication endpoint is rate-limited to **10 logins/minute per user** and **100 logins/minute per IP**. The single most important rule: **generate a token once, cache it, and reuse it** for the rest of its lifetime. Treat `POST /oauth2/token` as an expensive operation, not a per-call step.

### 1. Why this guide exists

Many integration issues we see — sudden `429 Too Many Requests` errors, broken cron jobs, flaky CI pipelines — trace back to one anti-pattern: **requesting a new token before every API call**. With a 24-hour token lifetime and a strict rate policy on the login endpoint, this pattern will eventually fail at scale.

This guide gives you the canonical lifecycle for tokens, the patterns to implement, and the mistakes to avoid.

### 2. The authentication policy in one table

| Limit          | Value                                       | Scope                         |
| -------------- | ------------------------------------------- | ----------------------------- |
| Token lifetime | **24 hours** (`expires_in: 86400`)          | per token                     |
| Login rate     | **10 / minute**                             | per user account              |
| Login rate     | **100 / minute**                            | per IP address                |
| Endpoint       | `POST https://api.iadvize.com/oauth2/token` | OAuth2, `grant_type=password` |

Going over either login limit returns an HTTP error and temporarily blocks further token generation from that user or IP.

### 3. The golden rule: cache and reuse

A single token lets you make as many GraphQL calls as you need for 24 hours. The pattern is always the same:

1. **First call** — request a token, store it in memory (or a secure shared store) with its expiry timestamp.
2. **Subsequent calls** — read the cached token and pass it in the `Authorization: Bearer …` header.
3. **Before expiry** — refresh the token *proactively*, ideally a few minutes before the 24-hour mark, not on failure.

If you have multiple processes (workers, lambdas, containers) sharing the same iAdvize user, **share the token between them** via Redis, a secret manager, or any centralized store. Each instance generating its own token will quickly exhaust the 10/min/user budget.

### 4. Reference implementation (Node.js)

A minimal in-memory cache with proactive refresh:

```javascript
const axios = require('axios');
const querystring = require('querystring');

const AUTH_URL = 'https://api.iadvize.com/oauth2/token';
const SAFETY_MARGIN_MS = 5 * 60 * 1000; // refresh 5 min before expiry

let cached = { token: null, expiresAt: 0 };

async function getAccessToken() {
  if (cached.token && Date.now() < cached.expiresAt - SAFETY_MARGIN_MS) {
    return cached.token;
  }

  const { data } = await axios.post(
    AUTH_URL,
    querystring.stringify({
      grant_type: 'password',
      username: process.env.IADVIZE_USER,
      password: process.env.IADVIZE_PASSWORD,
    }),
    { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }
  );

  cached = {
    token: data.access_token,
    expiresAt: Date.now() + data.expires_in * 1000,
  };
  return cached.token;
}
```

Every API call then does:

```javascript
const token = await getAccessToken();
await axios.post('https://api.iadvize.com/graphql', query, {
  headers: { Authorization: `Bearer ${token}` },
});
```

That's it. One login per 24 hours per process — well below the 10/min/user limit.

### 5. cURL equivalent (for scripts and CI)

```bash
# Generate once, store in a file or secret manager
TOKEN=$(curl -s --request POST \
  --url https://api.iadvize.com/oauth2/token \
  --data "username=$IADVIZE_USER&password=$IADVIZE_PASSWORD&grant_type=password" \
  | jq -r '.access_token')

# Reuse for all subsequent calls
curl --request POST \
  --url https://api.iadvize.com/graphql \
  --header "Content-Type: application/json" \
  --header "Authorization: Bearer $TOKEN" \
  --data "$QUERY"
```

For scheduled jobs, do **not** re-authenticate on every run. Persist the token to a secret store (AWS Secrets Manager, Vault, GCP Secret Manager) and rotate it on a separate daily schedule.

### 6. Handling rate-limit errors gracefully

If you do hit `429 Too Many Requests` on `/oauth2/token`, back off — do not retry immediately.

```javascript
async function getAccessTokenWithBackoff(attempt = 0) {
  try {
    return await getAccessToken();
  } catch (err) {
    if (err.response?.status === 429 && attempt < 4) {
      const delay = Math.pow(2, attempt) * 1000; // 1s, 2s, 4s, 8s
      await new Promise((r) => setTimeout(r, delay));
      return getAccessTokenWithBackoff(attempt + 1);
    }
    throw err;
  }
}
```

Exponential backoff is the standard pattern for rate-limited APIs and gives the per-minute counter time to reset.

### 7. Verifying a token

If you're unsure whether a stored token is still valid, hit the dedicated endpoint:

```bash
curl --request GET \
  --url https://api.iadvize.com/_authenticated \
  --header "Authorization: Bearer $TOKEN"
```

`{"authenticated": true}` means the token is good. `{"error": "invalid_token"}` means you need to regenerate.

Don't poll this endpoint — use it only when debugging or after a long downtime. Your normal flow should rely on the cached expiry timestamp.

### 8. Anti-patterns to avoid

* **Re-authenticating per request.** The most common cause of 429s.
* **One token per worker / lambda invocation.** With 10+ concurrent workers, you'll exceed 10/min/user within a single minute of cold starts.
* **Sharing one user across many independent integrations.** Create dedicated service users per integration so rate limits don't cross-contaminate.
* **Retrying on 429 without backoff.** This turns a 60-second wait into a permanent block.
* **Hardcoding tokens in code or repos.** Tokens last 24 hours — they must be stored in a secret manager and rotated, not committed.
* **Reacting to 401 by re-auth in a tight loop.** A bad password or revoked user will burn through your login budget in seconds.

### 9. Recommended architecture for production

For any integration calling iAdvize from multiple processes:

1. A single **token broker** (cron, lambda, or sidecar) calls `/oauth2/token` once per \~23 hours.
2. The broker writes the token to a **shared secret store** (Redis with TTL, Vault, AWS Secrets Manager).
3. All API clients **read** the token from that store — they never call `/oauth2/token` themselves.
4. The broker is the only component that needs to handle 429s, retries, and credential rotation.

This architecture stays comfortably under 1 login/minute/user, regardless of how many clients you run.


---

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

```
GET https://docs.iadvize.dev/technologies/graphql-api/guides/managing-iadvize-api-access-tokens.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.
