# quickbooks online oauth invalid_token expired error

## TL;DR
QuickBooks access tokens live about an hour, so integrations must refresh them continuously. Use the stored refresh token to mint a new pair, persist both (QuickBooks rotates the refresh token too), and retry the failed call. If the refresh itself fails, the grant is dead and the user must re-authorize. Schedule refreshes ahead of expiry rather than reacting to 401s.

```text
quickbooks online oauth invalid_token expired error
```

## Use this when

- QuickBooks Online API calls fail with invalid_token after working earlier
- The integration breaks roughly an hour after each reconnect
- Batch jobs fail overnight with token errors

## Not for this skill when

- invalid_grant during the first authorization (fix the authorize flow)
- QBO API returning 403 on valid tokens (company or scope permissions)
- Sandbox vs production company ID mixups

## Steps

### Step 1: Refresh the token pair

Call the token endpoint with the stored refresh token. Expected: a new access token and a new refresh token come back.

### Step 2: Persist both tokens

Store the new access token and the rotated refresh token, replacing the old ones everywhere. Expected: no worker still holds the previous refresh token, since reuse fails.

### Step 3: Retry the failed API call

Re-run the QuickBooks API call with the fresh access token. Expected: the call succeeds.

### Step 4: Schedule proactive refresh

Refresh on a timer well inside the token lifetime (for example every 50 minutes for active integrations) instead of waiting for a 401. Expected: tokens never expire mid-work.

### Step 5: Handle dead grants

If the refresh call itself fails with invalid_grant, mark the grant dead and prompt the user to re-authorize. Expected: a clear reconnect prompt instead of endless 401s.

## Tool compatibility

QuickBooks Online OAuth 2.0; Intuit developer app settings; background workers needing long-lived QBO access.

## Variant phrasings

### Variant 1

quickbooks online oauth access token expired invalid_token

### Variant 2

qbo api 401 invalid token refresh token

### Variant 3

quickbooks oauth token refresh failed reauthorize

## Why it happens

QuickBooks Online issues access tokens with a roughly one-hour lifetime and refresh tokens that rotate on every use and expire after about 100 days of disuse. That design punishes exactly the integration pattern people build first: authenticate once, store the access token, and call the API forever. The first hour works perfectly, then every call 401s at once. The second trap is refresh-token reuse: because each refresh invalidates the previous refresh token, two workers refreshing in parallel kill each other's tokens. The durable fix is a single token manager that refreshes proactively and serializes the operation.

## Edge cases / pitfalls

- Never let two processes refresh the same grant concurrently; use a lock or a single refresher.
- Sandbox and production tokens are not interchangeable; label storage by environment.
- A refresh token unused for 100 days dies silently; integrations with seasonal use need a keepalive or a planned re-auth.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_R0TFXGmq-P-XRhTI0BP7wA
