# Managing Access and Refresh Tokens

Handling tokens correctly is what keeps an integration running without repeatedly interrupting your customers. This page covers how NowInfinity tokens behave and what your integration needs to do with them.

## Token lifetimes

| Token | Lifetime | Purpose |
|  --- | --- | --- |
| Access token | 1 hour | Authenticates your API requests. |
| Refresh token | Up to 30 days | Obtains a new access token without user interaction. |


Read `expires_in` from the token response rather than hard-coding the access token lifetime — it is returned with every token, and reading it means your integration keeps working if the configured lifetime changes.

## Prerequisites

Before you begin:

- Valid client credentials for the environment you are working in.
- `offline_access` in your granted scope. Without it, no refresh token is issued.
- An understanding of the [Authorisation Code Flow](/products/nowinfinity/resources/authorisation-code-flow).


## Using access tokens

Send the access token as a Bearer token on every API request:

```
Authorization: Bearer {access_token}
```

Reuse the same access token for as many calls as you need until it expires. Track its expiry using the issuance time plus `expires_in`.

Do not request a new access token for every API call. It is unnecessary, slower, and puts avoidable load on the authorisation server.

## Refresh tokens rotate

**Refresh tokens are single-use.** Each time you exchange one for a new access token, the response includes a *new* refresh token, and the one you just used is immediately invalidated.

Your integration must:

1. Use the current refresh token to request a new access token.
2. Store the new refresh token returned in the response.
3. Discard the old one.


If you keep using the original refresh token, the second attempt fails with `invalid_grant`.

**Refresh in one place only.** If two workers, threads or scheduled jobs refresh the same token concurrently, one succeeds and invalidates the token the other is using — so the second fails with `invalid_grant`, and depending on how your code reacts you can lose the valid token entirely.

This is the most common cause of integrations that work in testing and fail under load. Serialise refreshes behind a lock, or handle refresh in a single dedicated process.

## Refreshing a token

Send an HTTP `POST` to the token endpoint:

| Parameter | Required | Value |
|  --- | --- | --- |
| `grant_type` | Yes | `refresh_token` |
| `refresh_token` | Yes | Your current refresh token |


```bash
curl -X POST https://auth.nowinfinity-test.com.au/connect/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=refresh_token" \
  -d "refresh_token={current_refresh_token}" \
  -d "client_id={your_client_id}" \
  -d "client_secret={your_client_secret}"
```

The response contains a new access token and a new refresh token. Store both immediately.

## Refresh proactively

Refresh before the access token expires rather than waiting for a `401`. Refreshing a few minutes early avoids failed requests and retry logic you would otherwise have to write.

## Storing tokens

- Store both tokens in your backend. Never expose them to a browser, mobile client or log file.
- Store the refresh token against the customer it belongs to. A refresh token is tied to the authorisation that produced it.
- Persist the new refresh token before you use the new access token, so a crash mid-cycle does not leave you holding an invalidated token.


## When refresh fails

A refresh token stops working when it expires, when it has already been used, or when the customer revokes your access. In each case the recovery is the same: start a new authorisation flow to obtain a fresh token pair.

Your integration should detect this and surface it to the customer as "reconnect your account", rather than retrying and failing silently.

## Revoking a token

The authorisation server exposes a revocation endpoint, published as `revocation_endpoint` in the [discovery document](/products/nowinfinity/resources/environments). Use it to invalidate a token when a customer disconnects your integration, rather than leaving a valid token outstanding until it expires.

## Related

- [Authorisation Scopes](/products/nowinfinity/resources/authorisation-scopes) — requesting `offline_access`.
- [Error codes](/products/nowinfinity/resources/error-codes) — diagnosing `invalid_grant`.
- [Authorisation Code Flow](/products/nowinfinity/resources/authorisation-code-flow) — starting a new authorisation.