> ## 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.

# OAuth authorization

> Learn how to use OAuth with Text APIs. Choose the right authorization flow and implement Implicit Grant, Authorization Code Grant, or Sign in with Text.

OAuth authorization lets your application access Text APIs on behalf of a user.

Instead of using a personal access token tied to a single account, OAuth allows each user to authorize your application with their own account. Your app then receives an `access_token` that can be used to call the APIs using that user's identity and permissions.

OAuth is typically used when building applications that other users install or sign in to — for example integrations or services that need to access data from multiple accounts.

This page explains the OAuth flows supported by Text:

* [Implicit grant](#implicit-grant)
* [Authorization code grant](#authorization-code-grant)
* [Sign in with Text](#sign-in-with-text)

These flows can be used to obtain an access token for calling APIs on behalf of an agent (like the Agent Chat API or the Configuration API). To authorize calls to the Customer Chat API, use [customer authorization](/authentication/customer-tokens/).

## Which OAuth flow to choose

The OAuth flow you choose depends on how your app works and where it runs.

| If you're building                                                  | Use this flow                                         |
| ------------------------------------------------------------------- | ----------------------------------------------------- |
| a web app that needs to get an access token directly in the browser | [Implicit grant](#implicit-grant)                     |
| a server-side app that can securely store a Client Secret           | [Authorization code grant](#authorization-code-grant) |
| a web app that needs a simple login flow                            | [Sign in with Text](#sign-in-with-text)               |

Use **Implicit grant** for browser-based apps that need to receive an `access_token` directly in the redirect URL.

Use **Authorization code grant** for server-side apps that can securely store a **Client Secret**. This flow also supports refreshing tokens without requiring the user to authorize again. If your frontend app needs to receive a `code` instead of an `access_token`, use **Authorization code grant with PKCE**.

Use **Sign in with Text** to add a ready-to-use login flow to a web app using the [Accounts SDK](#accounts-sdk). It's the simplest way to sign users in and obtain basic account data or an access token.

## OAuth configuration rules

### Token limitations

* There's a limit of 25 access tokens per client per user account. When the limit is reached, the oldest token is automatically revoked.

* There's a limit of 25 refresh tokens per client per user account. When the limit is reached, the oldest token is automaticaly revoked.

* There's a limit of 3 redirects in 30 seconds to the Text OAuth 2.1 server per client per user account. When the limit is reached, the server redirects to the error page with the `too_many_redirects` error details.

### Redirect URIs

You can configure many comma-separated redirect URIs for your application. The redirect URI in the Authorization request is valid when it matches one of the URIs configured for your OAuth client.

URIs are composed of several parts:

* **scheme** (`http://`, `https://`) - is required and must match exactly. See examples **10** and **11** in the table below.
* **host** (`google.pl`, `localhost:3000`, ...) - a hostname or IP and an optional port; is required and must match exactly. See examples **7**, **8**, and **9** in the table below.
* **path** (`/info`, `/test`, ...) - the client redirect URI path must be a substring of the authorization request redirect path; path traversals are forbidden. Optional. See examples **2**, **3**, **4**, **5**, and **6** in the table below.
* **query** (`?size=20`, ...) - is forbidden.
* **fragment** (`#paragraph`) - is forbidden.

Examples:

|    | Client redirect configuration                                                      | Authorization redirect URI                                                         | Is valid |
| -- | ---------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | -------- |
| 1  | [http://example.com](http://example.com)                                           | [http://example.com](http://example.com)                                           | yes      |
| 2  | [http://example.com](http://example.com)                                           | [http://example.com/archives](http://example.com/archives)                         | yes      |
| 3  | [http://example.com](http://example.com)                                           | [http://example.com/archives/../](http://example.com/archives/../)                 | no       |
| 4  | [http://example.com/archives](http://example.com/archives)                         | [http://example.com](http://example.com)                                           | no       |
| 5  | [http://example.com/archives](http://example.com/archives)                         | [http://example.com/archives](http://example.com/archives)                         | yes      |
| 6  | [http://example.com/archives](http://example.com/archives)                         | [http://example.com/archives/chats](http://example.com/archives/chats)             | yes      |
| 7  | <a href="http://localhost:3000">[http://localhost:3000](http://localhost:3000)</a> | <a href="http://localhost:3000">[http://localhost:3000](http://localhost:3000)</a> | yes      |
| 8  | [http://127.0.0.1:3000](http://127.0.0.1:3000)                                     | [http://127.0.0.1:3000](http://127.0.0.1:3000)                                     | yes      |
| 9  | <a href="http://localhost:3000">[http://localhost:3000](http://localhost:3000)</a> | <a href="http://localhost:4000">[http://localhost:4000](http://localhost:4000)</a> | no       |
| 10 | [https://example.com](https://example.com)                                         | [http://example.com](http://example.com)                                           | no       |
| 11 | [http://example.com](http://example.com)                                           | [https://example.com](https://example.com)                                         | no       |

## Implicit grant

Implicit grant is an authorization flow recommended for JavaScript web apps, but it works for both types: **JavaScript** and **server-side** apps.

To set up your own web app, you must define the URL of the app and the list of scopes. Scopes determine which parts of a Text user's account your app will have access to. A Text customer who enters your app URL will be asked to enter their login and password and grant the access for your app. Then, the user is redirected to your app with `access_token` included in the URL.

### Implementing implicit grant

#### Step 1: Create an app

In Text, 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 will be redirected after authorization
* **Access scopes** - permissions your app needs
* **Client type** - select **Web app** for browser-based JavaScript apps

After creating, Text shows your **Client ID** and **Secret key** once — copy the Client ID. Since this is the Implicit grant flow, you won't need the Secret key.

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

When users run your app, they should be redirected to the Text OAuth server, which can be found under this URL:

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

**Request**

| Parameter       | Required | Description                                                                                                                                                                                                                                                                 |
| --------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `response_type` | yes      | Value: `token`                                                                                                                                                                                                                                                              |
| `client_id`     | yes      | Your OAuth client's **Client Id**                                                                                                                                                                                                                                           |
| `redirect_uri`  | yes      | One of the URIs defined in the Authorization block during app configuration. The Text OAuth server will redirect the user back to this URI after successful authorization.                                                                                                  |
| `state`         | no       | Any value that might be useful to your application. It's strongly recommended to include an anti-forgery token to mitigate the <a href="https://en.wikipedia.org/wiki/Cross-site_request_forgery" target="_blank" rel="noopener noreferrer">cross-site request forgery</a>. |
| `prompt`        | no       | Value: `consent`. **For testing purposes.** It forces the app to ask for access to certain resources.                                                                                                                                                                       |

```shell title="Example redirection to Text OAuth server" theme={null}
https://accounts.livechat.com/
  ?response_type=token
  &client_id=9cbf3a968289727cb3cdfe83ab1d9836
  &redirect_uri=https%3A%2F%2Fmy-application.com
  &state=i8XNjC4b8KVok4uw5RftR38Wgp2BFwql
```

At this point, the app should ask the user to allow it to access certain resources and perform certain actions. The list of resources and actions is automatically created based on the scopes you configured for your OAuth client.

#### Step 3: Get an access token from the URL

After a user authorizes the app by clicking **Allow**, they are redirected back to your application (to the **Redirect URI** you configured). The URL includes a number of parameters, including the `access_token`.

**Response**

| Parameter      | Description                                                                                                                                                                     |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `access_token` | The token you can use to call Text APIs on behalf of the user.                                                                                                                  |
| `expires_in`   | The number of seconds the `access_token` will be valid; 28800 sec by default. When it expires, you will need to repeat the authorization process to get the new `access_token`. |
| `token_type`   | Value: `Bearer`                                                                                                                                                                 |
| `state`        | The value of the `state` param that you passed to Text OAuth server in redirection.                                                                                             |

```shell title="Example redirection back to the app" theme={null}
https://my-application.com/
  #access_token=dal%3Atest_DQTRHGbZCFkAoss4Q
  &token_type=Bearer
  &expires_in=28800
  &state=i8XNjC4b8KVok4uw5RftR38Wgp2BFwql
```

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

Once you extract the token from the URL, your app can use it to sign requests to the Text API.
Your application should store the `access_token` in localStorage or a cookie until it expires. Caching the token prevents you from redirecting the user to Text OAuth server every time they visit your app.

#### Code example

This sample web app makes a call to Agent Chat API to [return the list of customers](/api/agent-chat/), which is then logged in the console. The application uses the **Implicit grant** to get an access token.

```html title="index.html" theme={null}
<!DOCTYPE html>
<html>
  <body>
    <script src="/get_customers.js"></script>
    ​
    <script>
      function getHashParam(key) {
        var params = location.hash.substring(1).split("&");
        var value = params.find(function (item) {
          return item.split("=")[0] === key;
        });
        return value ? value.split("=")[1] : "";
      }

      const clientId = "bb9e5b2f1ab480e4a715977b7b1b4279"; // Client Id of your app
      const redirectUri = "https://get-customers-app.samplehosting.com/"; // URL of your app
      const accessToken = decodeURIComponent(getHashParam("access_token"));

      if (accessToken) {
        get_customers();
      } else {
        location.href =
          "https://accounts.livechat.com/" +
          "?response_type=token" +
          "&client_id=" +
          clientId +
          "&redirect_uri=" +
          redirectUri;
      }
    </script>
  </body>
</html>
```

```js title="get_customers.js" theme={null}
const get_customers = () => {
  fetch("https://api.livechat.com/v3.6/agent/action/list_customers", {
    method: "post",
    headers: {
      "Content-type": "application/json",
      Authorization: "Bearer " + accessToken,
    },
    body: JSON.stringify({}),
  })
    .then((response) => response.json())
    .then((data) => {
      console.log("Request succeeded with JSON response", data);
    })
    .catch((error) => {
      console.log("Request failed", error);
    });
};
```

To make it work, run this app on localhost or deploy it to Firebase to host it. Update `index.html` with your own `redirectUri` (link to your app) and `clientId`.
Make sure to use the exact same Redirect URI you configured for your OAuth client. To use the **Get Customers** method, your app needs the `customers:ro` scope.
When everything is ready, install the app privately for your license.

## Authorization code grant

Authorization code grant flow is recommended for server-side apps. Unlike web apps, they can store confidential info, such as **Client Secret**, on a server without ever exposing it.

When a user runs your app, they are redirected to the Text OAuth server. After successful authorization, the user is redirected back to your app with a single-use authorization code. Your application then exchanges the code for an access token and refresh token using the Client Secret. From this point, the app can regenerate new access tokens without any action from the user.

### PKCE extension

OAuth 2.1 introduces the <a href="https://oauth.net/2/pkce/" target="_blank">PKCE (Proof Key for Code Exchange)</a> extension for the Authorization code grant flow.
It allows web applications to use the Authorization code grant flow, and also, enables the possibility to use custom schema redirects, like: `my_app: //` (especially useful with native applications).

The **Authorization code grant flow with PKCE** is recommended for both **web apps** and **server-side apps**.
Since web app clients can't store Client Secrets securely, their Authorization code grant flow with PKCE differs from the one for server-side apps.

* **Web apps** - Client Secret cannot be used, so it's not mandatory; refresh tokens rotate.
* **Server-side apps** - Client Secret is mandatory to exchange a code for an access token and to refresh a token; refresh tokens don't rotate.

How does the Authorization code grant flow work with PKCE?

* The client generates `code_verifier` from the following characters: `[A-Z] / [a-z] / [0-9] / "-" / "." / "_" / "~"`. It's between 43 and 128 characters long.
* The client generates `code_challenge` with `code_challenge_method` as follows:
  * `plain` - `code_challenge` = `code_verifier`, when no `code_challenge_method` is present, then `plain` is assumed.
  * `S256` - `code_challenge` = `b64(s256(ascii(code_verifier)))` where `b64` is Base64 URL encoding and `s256` is the `SHA256` hash function.
* The client sends `code_challenge` in the authorization request.
* The server responds with the code.
* The client sends `code_verifier` during the exchange of the code for an access token.
* The server performs an additional validation for `code_challenge` and `code_verifier`. Upon successful validation, it returns the access token.

### Implementing authorization code grant

#### Step 1: Create and configure your app

In Text, 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 will be redirected after authorization; only this URI can receive the code or token
* **Access scopes** - select the scopes your app needs (e.g., `chats--all:ro` to list chats)
* **Client type** - select **Server-side app**

After creating, Text shows your **Client ID** and **Secret key** once — copy both immediately. The secret key won't be visible after you close that screen.

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

When users run your app, they should be redirected to the Text OAuth server, which can be found under this URL:

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

**Request**

| Parameter               | Required | Required with PKCE | Description                                                                                                                                                                                                               |
| ----------------------- | -------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `response_type`         | yes      | yes                | Value: `code`                                                                                                                                                                                                             |
| `client_id`             | yes      | yes                | Your OAuth client's **Client Id**                                                                                                                                                                                         |
| `redirect_uri`          | yes      | yes                | `redirect_uri` should be the same as `Direct installation URL` defined in the Authorization block during app configuration. The Text OAuth server will redirect the user back to this URI after successful authorization. |
| `state`                 | no       | no                 | Any value that might be useful to your application. It's strongly recommended to include an anti-forgery token to mitigate the [cross-site request forgery](https://en.wikipedia.org/wiki/Cross-site_request_forgery).    |
| `code_challenge`        | no       | yes                | A string between 43 and 128 characters long.                                                                                                                                                                              |
| `code_challenge_method` | -        | no                 | Possible values: `s256` or `plain`; default: `plain`.                                                                                                                                                                     |

<CodeGroup>
  ```shell title="Code grant" theme={null}
  https://accounts.livechat.com/
    ?response_type=code
    &client_id=9cbf3a968289727cb3cdfe83ab1d9836
    &redirect_uri=https%3A%2F%2Fmy-application.com
    &state=i8XNjC4b8KVok4uw5RftR38Wgp2BFwql
  ```

  ```shell title="Code grant 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=wuR7p4rc0UCqMx3r4jnwve1PqsiySUlf1pWVsCi1FqAeTZNQ5
    &code_challenge_method=plain
  ```
</CodeGroup>

At this point, the app should ask the user to allow it to access certain resources and perform certain actions. The list of resources and actions is automatically created based on the scopes you configured for your OAuth client.

Keep in mind that as the app author, you won't see this screen. Use `prompt:consent` to verify this step from the user perspective.
This step is also omitted for private server-side apps installed by Agents from the same license.

#### Step 3: Acquire the code

After a user authorizes the app by clicking **Allow**, they are redirected back to your application (to the **Redirect URI** you configured). The URL includes parameters, including the `code`.

**Response**

| Parameter | Notes                                                                                             |
| --------- | ------------------------------------------------------------------------------------------------- |
| `code`    | A single-use code you need to exchange it for an access token. It's only valid for a few minutes. |
| `state`   | The value of the `state` param that you passed to Text OAuth server in redirection.               |

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

#### Step 4: Exchange code for access token and refresh token

To exchange the `code` for an `access_token` and a `refresh_token`, you need to make an HTTP POST request to the following URL:

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

**Request**

| Parameter       | Required | Required with PKCE **server side app** | Required with PKCE **javascript app** | Description                                                                                                              |
| --------------- | -------- | -------------------------------------- | ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| `grant_type`    | yes      | yes                                    | yes                                   | Value: `authorization_code`                                                                                              |
| `code`          | yes      | yes                                    | yes                                   | The authorization code returned from the request in the previous step.                                                   |
| `client_id`     | yes      | yes                                    | yes                                   | Your OAuth client's **Client Id**                                                                                        |
| `client_secret` | yes      | yes                                    | no                                    | Your OAuth client's **Client Secret**.                                                                                   |
| `redirect_uri`  | yes      | yes                                    | yes                                   | The URI defined in Step 2. The Text OAuth server will redirect the user back to this URL after successful authorization. |
| `code_verifier` | no       | yes                                    | yes                                   | The previously generated `code_verifier`.                                                                                |

**Response**

The response is a JSON with the following parameters:

| Parameter         | Description                                                                                                                                                                                                                                                        |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `access_token`    | A token you can use to call Text APIs on behalf of the user.                                                                                                                                                                                                       |
| `account_id`      | The ID of the agent's account                                                                                                                                                                                                                                      |
| `expires_in`      | A number in seconds specifying how long the `access_token` will be valid; 28800 sec by default. When it expires, you will need to generate a new `access_token` using `refresh_token` (read [Using the refresh token](#using-the-refresh-token) for more details). |
| `organization_id` | The ID of the organization's account.                                                                                                                                                                                                                              |
| `refresh_token`   | A token that can be used to generate new access tokens.                                                                                                                                                                                                            |
| `scope`           | A comma-separated list of permissions an `access_token` has.                                                                                                                                                                                                       |
| `token_type`      | Value: `Bearer`                                                                                                                                                                                                                                                    |

<CodeGroup>
  ```shell title="Code grant" theme={null}
  curl "https://accounts.livechat.com/v2/token" \
    -X POST \
    -d "grant_type=authorization_code&\
    code=us-south1:test_tnlRmy73mg9eaFESA&\
    client_id=9cbf3a968289727cb3cdfe83ab1d9836&\
    client_secret=test_d7MEp1YYo3&\
    redirect_uri=https://my-application.com"
  ```

  ```shell title="Server-side app with PKCE" theme={null}
  curl "https://accounts.livechat.com/v2/token" \
    -X POST \
    -d "grant_type=authorization_code&\
    code=us-south1:test_tnlRmy73mg9eaFESA&\
    client_id=9cbf3a968289727cb3cdfe83ab1d9836&\
    client_secret=test_d7MEp1YYo3&\
    redirect_uri=https://my-application.com&\
    code_verifier=wuR7p4rc0UCqMx3r4jnwve1PqsiySUlf1pWVsCi1FqAeTZNQ5"
  ```

  ```shell title="Web app with PKCE" theme={null}
  curl "https://accounts.livechat.com/v2/token" \
    -X POST \
    -d "grant_type=authorization_code&\
    code=us-south1:test_tnlRmy73mg9eaFESA&\
    client_id=9cbf3a968289727cb3cdfe83ab1d9836&\
    redirect_uri=https://my-application.com&\
    code_verifier=wuR7p4rc0UCqMx3r4jnwve1PqsiySUlf1pWVsCi1FqAeTZNQ5"
  ```
</CodeGroup>

```json title="Response" theme={null}
{
  "access_token": "us-south1: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"
}
```

<Note>
  Refresh tokens no longer include the `us-south1:` or `eu-west3:` prefixes.
</Note>

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

Once you have the `access_token`, your app can use it to authorize requests to Text APIs. Store the token securely until it expires. Caching the token prevents unnecessary redirects to the Text OAuth server.

#### Practical example: Listing chats

Let's walk through a complete example. We'll use the [List Chats](/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 href="https://accounts.livechat.com" target="_blank">sign up</a> for free)
* An OAuth client configured with the `chats--all:ro` scope (see [Step 1](#step-1-create-and-configure-your-app))
* The `chats--all:ro` scope selected in your app
* A tool to send requests (Postman, cURL, etc.)

<Steps>
  <Step title="Get your code" id="get-your-code">
    Paste your **Client Id** and **Redirect URI** in this request format, then open it in your browser while logged in:

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

    After authorization, you'll be redirected to your Redirect URI with a `code` parameter:

    ```shell theme={null}
    https://www.example.com/?code=dal%3Ak0FTiZgtBkTLnzXlatwt6Fgvpp4&state=
    ```

    If the code contains `%3A`, replace it with `:` (colon). Example: `us-south1:k0FTiZgtBkTLnzXlatwt6Fgvpp4`
  </Step>

  <Step title="Exchange code for token" id="exchange-code-for-token">
    Use cURL or Postman to exchange the code for an access 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>"
    ```

    You'll receive a response with `access_token`, `refresh_token`, and other details.
  </Step>

  <Step title="Call the API" id="call-the-api">
    Use the access token to call the List Chats method. Copy the request from the [API documentation](/api/agent-chat/v3.6/chats/list-chats) and replace `<your_access_token>` with your actual token.

    <Tip>Find all requests in our <a href="https://app.getpostman.com/run-collection/20754404-ab4b398a-f906-4431-a17c-2f6673f0b8e8?action=collection%2Ffork&collection-url=entityId%3D20754404-ab4b398a-f906-4431-a17c-2f6673f0b8e8%26entityType%3Dcollection%26workspaceId%3D5e6fb31b-587b-4258-b215-4dccaae38a38" target="_blank">Postman collection</a>.</Tip>
  </Step>
</Steps>

### Using the refresh token

When an `access_token` expires, your app needs to acquire a new one. To do that, it has to send an HTTP POST request using the `refresh_token`.

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

**Request**

| Parameter       | Required | Required with PKCE **server side app** | Required with PKCE **javascript app** | Description                                                 |
| --------------- | -------- | -------------------------------------- | ------------------------------------- | ----------------------------------------------------------- |
| `grant_type`    | yes      | yes                                    | yes                                   | Value: `refresh_token`                                      |
| `refresh_token` | yes      | yes                                    | yes                                   | The refresh token returned from when exchanging the `code`. |
| `client_id`     | yes      | yes                                    | yes                                   | Your OAuth client's **Client Id**                           |
| `client_secret` | yes      | yes                                    | no                                    | Your OAuth client's **Client Secret**.                      |

**Response**

The response is a JSON with the following parameters:

| Parameter         | Description                                                                                                                                                                                                                                  |
| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `access_token`    | A token you can use to call Text APIs on behalf of the user.                                                                                                                                                                                 |
| `account_id`      | The ID of the agent's account                                                                                                                                                                                                                |
| `expires_in`      | A number in seconds specifying how long the `access_token` will be valid. When it expires, you will need to generate a new `access_token` using `refresh_token` (read [Using the refresh token](#using-the-refresh-token) for more details). |
| `organization_id` | the ID of the organization's account.                                                                                                                                                                                                        |
| `scope`           | A comma-separated list of permissions an `access_token` has.                                                                                                                                                                                 |
| `refresh_token`   | A token that can be used to generate new access tokens.                                                                                                                                                                                      |
| `token_type`      | Value: `Bearer`                                                                                                                                                                                                                              |

<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>

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

<Note>
  Refresh tokens no longer include the `us-south1:` or `eu-west3:` prefixes.
</Note>

### Revoking tokens

In some cases, a user may wish to revoke the access (the token) given to your application. The token can be either an access token or a refresh token. If it's an access token with a corresponding refresh token, both tokens will be revoked.
To revoke a token, make a DELETE HTTP request to the following URL:

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

**Request**

| Parameter | Required | Description                                                      |
| --------- | -------- | ---------------------------------------------------------------- |
| `code`    | yes      | The value of the `access_token` or the `refresh_token` to revoke |

<CodeGroup>
  ```shell title="Header" theme={null}
  curl "https://accounts.livechat.com/v2/token"
    -H "Authorization: Bearer <access_token|refresh token>"
    -X DELETE
  ```

  ```shell title="URL param" theme={null}
  curl "https://accounts.livechat.com/v2/token\
    ?code=us-south1:test_YTJQ6GDVgQf8kQDPw"
    -X DELETE
  ```
</CodeGroup>

```json title="Response (200 OK)" theme={null}
{}
```

### Validating the access token

You can validate an `access_token` by making a GET HTTP request to the following URL:

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

Please note that refresh tokens are not supported for direct validation. If an access token was obtained using a refresh token, the response will return both tokens.

**Response**

The response is a JSON with the following parameters:

| Parameter         | Description                                                                                                                                                                                                                                  |
| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `access_token`    | A token you can use to call Text APIs on behalf of the user.                                                                                                                                                                                 |
| `account_id`      | The ID of the agent's account                                                                                                                                                                                                                |
| `client_id`       | **Client Id** of your app                                                                                                                                                                                                                    |
| `expires_in`      | A number in seconds specifying how long the `access_token` will be valid. When it expires, you will need to generate a new `access_token` using `refresh_token` (read [Using the refresh token](#using-the-refresh-token) for more details). |
| `organization_id` | The ID of the organization's account.                                                                                                                                                                                                        |
| `scope`           | A comma-separated list of permissions an `access_token` has.                                                                                                                                                                                 |
| `refresh_token`   | A token that can be used to generate new access tokens. Returned optionally.                                                                                                                                                                 |
| `token_type`      | Value: `Bearer`                                                                                                                                                                                                                              |

```shell title="Validate an access token" theme={null}
curl "https://accounts.livechat.com/v2/info"
  -H "Authorization: Bearer <access_token>"
```

```json title="Response" theme={null}
{
  "access_token": "us-south1:test_YTJQ6GDVgQf8kQDPw",
  "account_id": "bbe8b147-d60e-46ac-a1e5-1e94b11ea6e1",
  "client_id": "9cbf3a968289727cb3cdfe83ab1d9836",
  "expires_in": 28725,
  "organization_id": "390e44e6-f1e6-0368c-z6ddb-74g14508c2ex",
  "scope": "chats--all:ro,chats--all:rw",
  "token_type": "Bearer"
}
```

## Sign in with Text

The **Sign in with Text** flow is the easiest way to get access to basic information in Text accounts. It allows you to quickly build an app that can access that info through Accounts SDK.

The **Sign in with Text** flow lets you:

* Get access to the Text user's email, account ID, or organization ID.
* Receive an `access_token` that can be used to perform API calls.
* Receive a `code` using the PKCE extension, which could be then used to obtain the account's `refresh_token` and `access_token`.

### User flow

Users start the flow by clicking the **Sign in with Text** button. If a user is not signed in, they'll be asked to do that.

Then, the user must give the app access to the specified parts of their Text account.

Finally, the app receives an `access_token` that allows it to perform different API calls, limited to what the user agreed to in the prompt.

For example, you can display the tracking code which already includes the user's account license number:

```html title="Tracking code" theme={null}
<!-- Start of Text (www.text.com) code -->
<script>
  window.__lc = window.__lc || {};
  window.__lc.organizationId = "<ORGANIZATION_ID>";
  window.__lc.integration_name = "manual_onboarding";
  window.__lc.product_name = "text";
  (function (n, t, c) {
    function i(n) {
      return e._h ? e._h.apply(null, n) : e._q.push(n);
    }
    var e = {
      _q: [],
      _h: null,
      _v: "2.0",
      on: function () {
        i(["on", c.call(arguments)]);
      },
      once: function () {
        i(["once", c.call(arguments)]);
      },
      off: function () {
        i(["off", c.call(arguments)]);
      },
      get: function () {
        if (!e._h)
          throw new Error(
            "[LiveChatWidget] You can't use getters before load.",
          );
        return i(["get", c.call(arguments)]);
      },
      call: function () {
        i(["call", c.call(arguments)]);
      },
      init: function () {
        var n = t.createElement("script");
        ((n.async = !0),
          (n.type = "text/javascript"),
          (n.src = "https://cdn.livechatinc.com/tracking.js"),
          t.head.appendChild(n));
      },
    };
    (!n.__lc.asyncInit && e.init(), (n.LiveChatWidget = n.LiveChatWidget || e));
  })(window, document, [].slice);
</script>
<noscript
  ><a
    href="https://www.text.com/chat-with-ai-agent/<ORGANIZATION_ID>/"
    rel="nofollow"
    >Chat with AI agent</a
  >, powered by
  <a href="https://www.text.com/" rel="noopener nofollow" target="_blank"
    >Text</a
  ></noscript
>
<!-- End of Text code -->
```

### Implementing Sign in with Text

#### Step 1: Create a new app

In Text, 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** - must match the exact URL of the website where users will click **Sign in with Text**; the button will not work with any other URL
* **Access scopes** - permissions your app needs

After creating, Text shows your **Client ID** and **Secret key** once — copy both immediately. The secret key won't be visible after you close that screen.

#### Step 2: Include the SDK library

You can install the SDK from NPM.

**NPM module**

```bash title="NPM module installation" theme={null}
npm install --save @livechat/accounts-sdk@^2.0.0
```

```js title="NPM module import" theme={null}
import AccountsSDK from "@livechat/accounts-sdk";
```

If you build an app using Webpack, you can just import the `AccountsSDK` module from NPM.

#### Step 3: Prepare button container

Prepare the login button, which will invoke the authorization flow when a user clicks it.

```html theme={null}
<div id="login-button" style="background: url(.../livechat_sign_in.png)"></div>
```

```js title="Prepare the button container" theme={null}
// javascript
const instance = new AccountsSDK({
  client_id: "<your_app_client_id>",
  redirect_uri: "<your_app_redirect_uri>",
});

document.getElementById("login-button").onclick = (e) => {
  if (e && e.preventDefault) {
    e.preventDefault();
  }

  instance
    .popup()
    .authorize()
    .then((authorizeData) => {
      const transaction = instance.verify(authorizeData);
      if (transaction != null) {
        // authorization success
        // authorizeData contains `accessToken` or `code`
        // transaction contains state and optional code_verifier (code + PKCE)
        console.log("User access token: " + transaction.accessToken);
        document.getElementById("login-button").style.display = "none";
      } else {
        console.log("Redirect state doesn't match the previous one");
      }
    })
    .catch((e) => {
      console.error("Failed to authorize user", e);
    });
};
```

<Tip>
  Use `prompt: "consent"` to force the app to ask you for access to certain
  resources.
</Tip>

### Accounts SDK

The Accounts SDK (`@livechat/accounts-sdk`) provides the classes and methods used in the Sign in with Text flow. For the full API reference — including `AccountsSDK`, `Popup`, `Redirect`, PKCE configuration, and response formats — see the [Accounts SDK documentation](/sdk/accounts-sdk).
