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

# Exchange Code

## Overview

Exchange an authorization code for a JWT API key. This is the final step in the OAuth2 flow, converting the temporary code into a permanent access token.

<Info>
  This endpoint requires the `X-OAuth2-Client-Secret` header for authentication instead
  of the standard `Authorization` header.
</Info>

## Path Parameters

| Parameter | Type | Description |
| - | - | - |
| `appId` | string | Your application's Client ID |
| `code` | string | The authorization code received from the callback |

## Headers

| Header | Required | Description |
| - | - | - |
| `X-OAuth2-Client-Secret` | Yes | Your application's 72-character client secret |
| `User-Agent` | Yes | Your application identifier |

<Warning>
  **Server-Side Only**: This request must be made from your backend server,
  never from client-side code. The client secret must remain confidential.
</Warning>

## Response

```json theme={null}
{
  "success": true,
  "data": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
```

The `data` field contains a JWT API key that you can use to make authenticated API requests.

## Using the API Key

Include the JWT as a Bearer token in subsequent API requests:

```bash theme={null}
curl -X GET https://api.komerza.com/stores/STORE_ID \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
  -H "User-Agent: MyApp/1.0"
```

## Token Properties

The JWT API key:

* **Grants access** only to the stores the user authorized
* **Has permissions** limited to the scopes you requested and the user approved
* **Does not expire** until the user revokes authorization
* **Is tied** to the specific user and application

## Error Responses

| Error | Description |
| - | - |
| `invalid_code` | The authorization code is invalid or has already been used |
| `code_expired` | The authorization code has expired (codes are valid for 1 minute) |
| `invalid_client_secret` | The client secret is incorrect |
| `app_not_found` | The application ID is invalid |

## Complete Flow Example

```javascript theme={null}
// 1. User clicks "Connect with Komerza" in your app
const authUrl = `https://dashboard.komerza.com/auth/authorize?client_id=${CLIENT_ID}&redirect_uri=${REDIRECT_URI}&state=${randomState}`;
window.location.href = authUrl;

// 2. User authorizes on Komerza, redirected back to your app
// URL: https://myapp.com/callback?code=ENCRYPTED_CODE&state=randomState

// 3. Your backend exchanges the code for an API key
const response = await fetch(
  `https://api.komerza.com/oauth2/${CLIENT_ID}/exchange/${code}`,
  {
    headers: {
      "X-OAuth2-Client-Secret": process.env.CLIENT_SECRET,
      "User-Agent": "MyApp/1.0",
    },
  }
);

const { data: apiKey } = await response.json();

// 4. Store the API key securely and use it for API calls
const stores = await fetch("https://api.komerza.com/stores", {
  headers: {
    Authorization: `Bearer ${apiKey}`,
    "User-Agent": "MyApp/1.0",
  },
});
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.