# Fix Intercom OAuth failing with invalid authorization code

## TL;DR
Invalid authorization code means the code Intercom sent was already used, expired, or never valid. Authorization codes are single-use and expire in minutes, so exchange each code immediately and exactly once. If your code retries the exchange, the retry is what fails.

## The error
```text
Intercom OAuth failed
{"error":"invalid_grant","error_description":"Invalid authorization code"}
```

## Use this skill
Agent? Search Vectle for this error:
```bash
curl -s "https://vectle.com/api/v1/search?q=intercom oauth invalid authorization code error"
```

## Fix it

### Step 1: Check for double exchange in your code

```bash
Search your OAuth callback handler for the token exchange call and confirm it runs once per code.
```

Expected: You find either a single call or a retry path that reuses the code.

### Step 2: Remove code reuse and retries

```bash
Make the exchange fire exactly once; on failure, restart the whole authorization flow instead of retrying the code.
```

Expected: Each authorization code is exchanged at most once.

### Step 3: Exchange the code immediately

```bash
Keep the time between receiving the code and exchanging it as short as possible.
```

Expected: Exchanges complete within seconds of receiving the code.

### Step 4: Verify the redirect URI matches

```bash
Confirm the redirect_uri sent at exchange time matches the one sent at authorize time.
```

Expected: Both values are identical.

### Step 5: Test a fresh OAuth flow

```bash
Run the full flow again from authorization.
```

Expected: The exchange returns tokens on the first try.

## When this applies

- Intercom OAuth fails with invalid authorization code
- The flow works sometimes and fails other times
- You added retry logic to the OAuth callback

## When it doesn't

- The error is invalid_client (check the app credentials)
- The code is never received (check the redirect URI registration)
- Tokens are issued but API calls fail (check scopes)

## Compatibility

Intercom OAuth 2.0 for apps. Authorization code flow.

## Variant phrasings

### intercom invalid_grant authorization code

Same failure. invalid_grant is the wrapper; the description names the code as the problem.

### oauth code already used intercom

Already-used is the top cause when retry logic replays the exchange.

### intercom oauth code expired

Codes expire quickly. Slow exchanges, like ones waiting on a user step, die before they run.

## Why it happens

Authorization codes are single-use, short-lived credentials by design. The first exchange consumes the code; anything after that, a retry, a double-submit, a replayed webhook, gets invalid authorization code. Expired codes fail the same way when the exchange happens too late.

## Edge cases

- Browser back-button resubmits can double-fire the exchange; guard with a state check
- Load-balanced callback handlers can race on the same code; make the exchange idempotent at the flow level
- Logging the code is a security risk; log the state parameter instead

## If it still fails

- Reproduce with one API call in isolation, outside the agent, to separate platform issues from agent issues.
- Check the platform status page and changelog; OAuth and webhook behaviors change without warning.
- Capture the full request and response with timestamps for the vendor ticket, redacting credentials.
- Test in a second workspace or sandbox to rule out workspace-specific policy blocks.
- If the integration is business-critical, build the fallback now: cached data, a manual trigger, or a second provider.

## Prevention

- Store OAuth credentials in a secrets manager with rotation reminders.
- Build the reconnect flow before you need it; every integration gets revoked eventually.
- Log token ages so expiring grants are visible ahead of time.
- Keep a sandbox integration for testing config changes.
- Document the required scopes per integration so reinstalls request the right ones.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_osJIsJs0T7uBKAOD7ejUyg
