> ## Documentation Index
> Fetch the complete documentation index at: https://docs.baanx.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Exchange Code for Tokens

> Final OAuth step - exchange authorization code or refresh token for access tokens

## Overview

Exchange an authorization code or refresh token for access tokens. Supports two grant types:

1. **Authorization Code** (`grant_type=authorization_code`) - Step 4 of OAuth flow
2. **Refresh Token** (`grant_type=refresh_token`) - Renew expired access tokens

## Request

### Body Parameters

<ParamField body="grant_type" type="string" required>
  Type of token exchange

  **Values**: `authorization_code` | `refresh_token`
</ParamField>

<ParamField body="code" type="string">
  Authorization code from Step 3

  **Required for**: `authorization_code` grant
</ParamField>

<ParamField body="redirect_uri" type="string">
  Must exactly match URI from Step 1

  **Required for**: `authorization_code` grant
</ParamField>

<ParamField body="code_verifier" type="string">
  Original PKCE verifier from Step 1 (43-128 chars)

  **Required for**: `authorization_code` grant

  **Pattern**: `[A-Za-z0-9-._~]{43,128}`
</ParamField>

<ParamField body="refresh_token" type="string">
  Refresh token from previous exchange

  **Required for**: `refresh_token` grant
</ParamField>

## Response

<ResponseField name="access_token" type="string">
  Bearer token for API authentication (6 hours expiry)

  **Example**: `access_token_100a99cf-f4d3-4fa1-9be9-2e9828b20ebc`
</ResponseField>

<ResponseField name="expires_in" type="number">
  Access token lifetime in seconds (21600 = 6 hours)
</ResponseField>

<ResponseField name="refresh_token" type="string">
  Token for obtaining new access tokens (184 days expiry)

  **Example**: `refresh_token_100a99cf-f4d3-4fa1-9be9-2e9828b20ebd`
</ResponseField>

<ResponseField name="refresh_token_expires_in" type="number">
  Refresh token lifetime in seconds (15897600 = 184 days)
</ResponseField>

## Code Examples

<CodeGroup>
  ```bash Authorization Code theme={null}
  curl -X POST "https://dev.api.baanx.com/v1/auth/oauth/token" \
    -H "x-client-key: your-client-key" \
    -H "Content-Type: application/json" \
    -d '{
      "grant_type": "authorization_code",
      "code": "auth_code_xyz123",
      "redirect_uri": "https://yourapp.com/callback",
      "code_verifier": "bbdbb44b57e78fbdf7254757bc62de8ce2b5342c"
    }'
  ```

  ```bash Refresh Token theme={null}
  curl -X POST "https://dev.api.baanx.com/v1/auth/oauth/token" \
    -H "x-client-key: your-client-key" \
    -H "Content-Type: application/json" \
    -d '{
      "grant_type": "refresh_token",
      "refresh_token": "refresh_token_abc123"
    }'
  ```

  ```javascript Token Refresh Logic theme={null}
  async function getValidToken() {
    let accessToken = localStorage.getItem('access_token');
    const expiresAt = parseInt(localStorage.getItem('token_expires_at'));

    // Check if token expired or about to expire (5 min buffer)
    if (Date.now() >= expiresAt - 300000) {
      const refreshToken = localStorage.getItem('refresh_token');

      const response = await fetch('https://dev.api.baanx.com/v1/auth/oauth/token', {
        method: 'POST',
        headers: {
          'x-client-key': 'your-client-key',
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          grant_type: 'refresh_token',
          refresh_token: refreshToken
        })
      });

      const data = await response.json();

      // Store new tokens
      accessToken = data.access_token;
      localStorage.setItem('access_token', data.access_token);
      localStorage.setItem('refresh_token', data.refresh_token);
      localStorage.setItem('token_expires_at', Date.now() + data.expires_in * 1000);
    }

    return accessToken;
  }
  ```
</CodeGroup>

<Tip>
  Implement automatic token refresh 5 minutes before expiry to ensure uninterrupted API access.
</Tip>
