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

# Authorization code grant

> Implement the OAuth authorization code grant, with PKCE, to get access and refresh tokens for Text APIs.

The authorization code grant works the same way for both client types: the user is redirected to the Text OAuth server, and after they authorize your app, they're redirected back with a single-use authorization `code`. Your app then exchanges that code for an `access_token` and a `refresh_token`.

* **Server-side apps** authenticate this exchange with their **Client Secret**. They can also add PKCE, but PKCE doesn't replace the Client Secret.
* **Web apps** can't hold a Client Secret, so PKCE is required instead.

## PKCE extension

OAuth 2.1 requires the <a href="https://oauth.net/2/pkce/" target="_blank">PKCE (Proof Key for Code Exchange)</a> extension for public clients using the authorization code grant. It also enables Web app clients to use a custom-scheme redirect URI, like `myapp://callback` — useful for native applications. See [Redirect URIs](/docs/authentication/oauth-authorization#redirect-uris) for the scheme rules.

How PKCE works:

1. The client generates a `code_verifier`: a random string of 43 to 128 characters from `[A-Z] [a-z] [0-9] - . _ ~`.
2. The client derives a `code_challenge` from the `code_verifier` using the method in `code_challenge_method`:
   * `S256` — `code_challenge` is the Base64 URL-encoded SHA-256 hash of `code_verifier`. Use this method.
   * `plain` — `code_challenge` equals `code_verifier`. Used if `code_challenge_method` is omitted.
3. The client sends `code_challenge` and `code_challenge_method` in the authorization request.
4. The server returns the authorization `code`.
5. The client sends the original `code_verifier` when exchanging the code for a token.
6. The server checks `code_verifier` against the `code_challenge` from step 3 and, if it matches, returns the `access_token`.

Generate `code_verifier` and `code_challenge` in the browser with the Web Crypto API:

```js title="Generate a PKCE code_verifier and code_challenge" theme={null}
const base64url = (bytes) =>
  btoa(String.fromCharCode(...bytes))
    .replace(/\+/g, "-")
    .replace(/\//g, "_")
    .replace(/=+$/, "");

const codeVerifier = base64url(crypto.getRandomValues(new Uint8Array(32)));
const challengeBytes = new Uint8Array(
  await crypto.subtle.digest("SHA-256", new TextEncoder().encode(codeVerifier)),
);
const codeChallenge = base64url(challengeBytes);
```

Store `codeVerifier` until you exchange the code — you'll send it as `code_verifier` in [Step 4](#step-4-exchange-the-code-for-tokens). Don't send it in the authorization request.

## Implementing the authorization code grant

### Step 1: Create an OAuth client

Go to [Settings → API access → OAuth clients](https://www.text.com/app/settings/integrations/api-access/oauth-clients) and create a new OAuth client. Configure:

* **Display name** — a name to identify your OAuth client.
* **Redirect URI whitelist** — where users are redirected after authorization. See [Redirect URIs](/docs/authentication/oauth-authorization#redirect-uris) for the rules governing this value.
* **Access scopes** — the scopes your app needs (for example, `chats--all:ro` to list chats). See [OAuth scopes](/docs/authentication/scopes) for the full list.
* **Client type** — **Web app** or **Server-side app**, depending on where your app runs.

After creation, Text shows your **Client ID** and, for server-side apps, your **Client Secret** once. Copy both immediately — the secret isn't shown again.

<Warning>
  Never include a Client Secret in browser code, a mobile app, a public
  repository, or a URL. Anyone who can read it can impersonate your OAuth
  client.
</Warning>

### Step 2: Redirect users to the Text OAuth server

Redirect users to:

```url theme={null}
https://accounts.livechat.com/
```

**Request parameters**

| Parameter | Required | Description |
| - | - | - |
| `response_type` | yes | Value: `code`. |
| `client_id` | yes | Your OAuth client's **Client ID**. |
| `redirect_uri` | yes | One of the URIs configured for your OAuth client. See [Redirect URIs](/docs/authentication/oauth-authorization#redirect-uris) for matching rules. |
| `state` | no | An anti-forgery token to mitigate <a href="https://en.wikipedia.org/wiki/Cross-site_request_forgery" target="_blank" rel="noopener noreferrer">cross-site request forgery</a>. |
| `code_challenge` | yes for Web app clients | The PKCE code challenge, 43 to 128 characters long. |
| `code_challenge_method` | no | `S256` or `plain`. Default: `plain`. |

```shell title="Authorization request with PKCE" theme={null}
https://accounts.livechat.com/
  ?response_type=code
  &client_id=9cbf3a968289727cb3cdfe83ab1d9836
  &redirect_uri=https%3A%2F%2Fmy-application.com
  &state=i8XNjC4b8KVok4uw5RftR38Wgp2BFwql
  &code_challenge=WJ0n9-UvKyEKNlD1gCUMc2mt2ST99gGE3MBSPdBDwvU
  &code_challenge_method=S256
```

At this point, the user is asked to allow your app to access the resources covered by your client's configured scopes. Use `prompt=consent` to trigger this screen again for testing.

### Step 3: Acquire the code

After the user clicks **Allow**, Text redirects them back to your `redirect_uri` with a `code` parameter:

```shell title="Example redirection back to the app" theme={null}
https://my-application.com/
  ?code=test_7W91a-oMsCeLvIaQm6bTrgtp7
  &state=i8XNjC4b8KVok4uw5RftR38Wgp2BFwql
```

The `code` is single-use and valid for only a few minutes. Compare the returned `state` with the value you sent in Step 2, and reject the request if they don't match, before exchanging the code.

If authorization fails, Text redirects back with `error` and, optionally, `error_description` instead of `code`. See [Authorization errors](/docs/authentication/errors) for the possible values.

### Step 4: Exchange the code for tokens

Make an HTTP POST request to:

```shell theme={null}
https://accounts.livechat.com/v2/token
```

Text accepts this request as either form-encoded or JSON.

**Request parameters**

| Parameter | Required | Description |
| - | - | - |
| `grant_type` | yes | Value: `authorization_code`. |
| `code` | yes | The authorization code from the previous step. |
| `client_id` | yes | Your OAuth client's **Client ID**. |
| `client_secret` | yes for server-side apps | Your OAuth client's **Client Secret**. Not used for Web app clients. |
| `redirect_uri` | yes | The same `redirect_uri` used in the authorization request. |
| `code_verifier` | yes for Web app clients | The `code_verifier` you generated for [PKCE](#pkce-extension). Optional for server-side apps using PKCE. |

<CodeGroup>
  ```shell title="Form-encoded (server-side app)" theme={null}
  curl "https://accounts.livechat.com/v2/token" \
    -X POST \
    -d "grant_type=authorization_code&code=test_7W91a-oMsCeLvIaQm6bTrgtp7&client_id=9cbf3a968289727cb3cdfe83ab1d9836&client_secret=test_d7MEp1YYo3&redirect_uri=https://my-application.com"
  ```

  ```shell title="Form-encoded (Web app with PKCE)" theme={null}
  curl "https://accounts.livechat.com/v2/token" \
    -X POST \
    -d "grant_type=authorization_code&code=test_7W91a-oMsCeLvIaQm6bTrgtp7&client_id=9cbf3a968289727cb3cdfe83ab1d9836&redirect_uri=https://my-application.com&code_verifier=wuR7p4rc0UCqMx3r4jnwve1PqsiySUlf1pWVsCi1FqAeTZNQ5"
  ```

  ```shell title="JSON (Web app with PKCE)" theme={null}
  curl "https://accounts.livechat.com/v2/token" \
    -X POST \
    -H "Content-Type: application/json" \
    -d '{
      "grant_type": "authorization_code",
      "code": "test_7W91a-oMsCeLvIaQm6bTrgtp7",
      "client_id": "9cbf3a968289727cb3cdfe83ab1d9836",
      "redirect_uri": "https://my-application.com",
      "code_verifier": "wuR7p4rc0UCqMx3r4jnwve1PqsiySUlf1pWVsCi1FqAeTZNQ5"
    }'
  ```
</CodeGroup>

**Response**

| Parameter | Description |
| - | - |
| `access_token` | The token you use to call Text APIs on behalf of the user. |
| `refresh_token` | The token you use to generate new access tokens. See [Using the refresh token](#using-the-refresh-token). |
| `account_id` | The ID of the agent's account. |
| `organization_id` | The ID of the organization's account. |
| `expires_in` | The number of seconds until `access_token` expires; 28800 by default. |
| `scope` | A comma-separated list of permissions granted to `access_token`. |
| `token_type` | Value: `Bearer`. |

```json title="Response" theme={null}
{
  "access_token": "test_YTJQ6GDVgQf8kQDPw",
  "account_id": "b7eff798-f8df-4364-8059-649c35c9ed0c",
  "expires_in": 28800,
  "organization_id": "390e44e6-f1e6-0368c-z6ddb-74g14508c2ex",
  "refresh_token": "test_gfalskcakg2347o8326",
  "scope": "chats--all:ro,chats--all:rw",
  "token_type": "Bearer"
}
```

### Step 5: Use the token in API calls

Use `access_token` to authorize requests to Text APIs. Store the token securely until it expires — caching it avoids unnecessary redirects to the Text OAuth server.

## Practical example: listing chats

This example walks through the authorization code grant to call the [List Chats](/docs/api/agent-chat/v3.6/chats/list-chats) method from the Agent Chat API.

Before you start, make sure you have:

* A Text Owner or Admin account.
* A Server-side app OAuth client configured with the `chats--all:ro` scope (see [Step 1](#step-1-create-an-oauth-client)) — this example exchanges the code with a Client Secret.
* A tool to send requests, such as cURL or Postman.

<Steps>
  <Step title="Get your code">
    Open this URL in your browser while logged in, replacing the placeholders with your own values:

    ```shell theme={null}
    https://accounts.livechat.com/
      ?response_type=code
      &client_id=<YOUR_CLIENT_ID>
      &redirect_uri=<YOUR_REDIRECT_URI>
    ```

    After you authorize the request, Text redirects you to your redirect URI with a `code` parameter:

    ```shell theme={null}
    https://www.example.com/?code=test_k0FTiZgtBkTLnzXlatwt6Fgvpp4&state=
    ```
  </Step>

  <Step title="Exchange the code for a token">
    ```shell theme={null}
    curl "https://accounts.livechat.com/v2/token" \
      -X POST \
      -d "grant_type=authorization_code&code=<YOUR_CODE>&client_id=<YOUR_CLIENT_ID>&client_secret=<YOUR_CLIENT_SECRET>&redirect_uri=<YOUR_REDIRECT_URI>"
    ```

    The response includes `access_token`, `refresh_token`, and the other fields described in [Step 4](#step-4-exchange-the-code-for-tokens).
  </Step>

  <Step title="Call the API">
    Call [List Chats](/docs/api/agent-chat/v3.6/chats/list-chats), replacing the placeholder token with your `access_token`:

    ```shell theme={null}
    curl "https://api.livechatinc.com/v3.6/agent/action/list_chats" \
      -X POST \
      -H "Authorization: Bearer <YOUR_ACCESS_TOKEN>" \
      -H "Content-Type: application/json" \
      -d '{}'
    ```
  </Step>
</Steps>

## Using the refresh token

When `access_token` expires, exchange `refresh_token` for a new one with an HTTP POST request:

```url theme={null}
https://accounts.livechat.com/v2/token
```

**Request parameters**

| Parameter | Required | Description |
| - | - | - |
| `grant_type` | yes | Value: `refresh_token`. |
| `refresh_token` | yes | The refresh token from the code exchange or a previous refresh. |
| `client_id` | yes | Your OAuth client's **Client ID**. |
| `client_secret` | yes for server-side apps | Your OAuth client's **Client Secret**. |

<Warning>
  For Web app clients, `refresh_token` rotates: every successful refresh
  invalidates the previous refresh token and returns a new one. Always save the
  `refresh_token` from the response, or the next refresh will fail. Server-side
  app refresh tokens don't rotate.
</Warning>

<CodeGroup>
  ```shell title="Server-side app" theme={null}
  curl "https://accounts.livechat.com/v2/token" \
    -X POST \
    -d "grant_type=refresh_token&refresh_token=test_gfalskcakg2347o8326&client_id=9cbf3a968289727cb3cdfe83ab1d9836&client_secret=test_d7MEp1YYo3"
  ```

  ```shell title="Web app" theme={null}
  curl "https://accounts.livechat.com/v2/token" \
    -X POST \
    -d "grant_type=refresh_token&refresh_token=test_gfalskcakg2347o8326&client_id=9cbf3a968289727cb3cdfe83ab1d9836"
  ```
</CodeGroup>

The response has the same shape as the code exchange response in [Step 4](#step-4-exchange-the-code-for-tokens).


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