---
title: Google Chat
description: Google Chat adapter with service account auth and optional Pub/Sub.
tagline: Integrate with Google Chat spaces for team collaboration and automated workflows.
package: @chat-adapter/gchat
---

# Google Chat



## Install

<PackageInstall package="@chat-adapter/gchat" />

## Quick start

<Callout type="info">
  The adapter auto-detects `GOOGLE_CHAT_CREDENTIALS` (or `GOOGLE_CHAT_USE_ADC`) from the environment.
</Callout>

```typescript title="lib/bot.ts" lineNumbers
import { Chat } from "chat";
import { createGoogleChatAdapter } from "@chat-adapter/gchat";

const bot = new Chat({
  userName: "mybot",
  adapters: {
    gchat: createGoogleChatAdapter(),
  },
});

bot.onNewMention(async (thread, message) => {
  await thread.post("Hello from Google Chat!");
});
```

## Configuration

<TypeTable
  type={{
  credentials: {
    type: "ServiceAccountCredentials",
    description:
      "Service account credentials JSON. Auto-detected from `GOOGLE_CHAT_CREDENTIALS`.",
  },
  useApplicationDefaultCredentials: {
    type: "boolean",
    description:
      "Use Application Default Credentials. Auto-detected from `GOOGLE_CHAT_USE_ADC`.",
  },
  pubsubTopic: {
    type: "string",
    description:
      "Pub/Sub topic for Workspace Events. Auto-detected from `GOOGLE_CHAT_PUBSUB_TOPIC`.",
  },
  pubsubAudience: {
    type: "string",
    description:
      "Expected JWT audience for Pub/Sub webhook verification.",
  },
  googleChatProjectNumber: {
    type: "string",
    description:
      "GCP project number for direct webhook JWT verification. Use when the Chat app's authentication audience is set to 'Project number'.",
  },
  endpointUrl: {
    type: "string",
    description:
      "Public URL of the webhook endpoint. Required for routing button click actions to your app, and used as an accepted JWT audience for direct webhooks when the Chat app's authentication audience is set to 'HTTP endpoint URL'.",
  },
  impersonateUser: {
    type: "string",
    description:
      "User email for domain-wide delegation. Required for fetching message history and DMs.",
  },
  apiUrl: {
    type: "string",
    description: "Override the Google Chat API base URL.",
  },
}}
/>

One of `googleChatProjectNumber`, `endpointUrl`, `pubsubAudience`, or `disableSignatureVerification: true` is required — the constructor throws otherwise. Configure the verifier(s) for each transport you actually receive.

## Authentication

### 1. Create a GCP project

1. Go to [console.cloud.google.com](https://console.cloud.google.com) and create a project.
2. Enable **Google Chat API**, **Google Workspace Events API** (for receiving all messages), and **Cloud Pub/Sub API**.

### 2. Create a service account

1. Open **IAM & Admin** then **Service Accounts** and click **Create Service Account**.
2. After creation, open the account and go to the **Keys** tab.
3. Click **Add Key** then **Create new key** then **JSON**.
4. Copy the JSON to `GOOGLE_CHAT_CREDENTIALS`.

<Callout type="warn">
  If your organization has the `iam.disableServiceAccountKeyCreation` constraint enabled, you need to relax it or add a project exception under **IAM & Admin** then **Organization Policies**.
</Callout>

### 3. Configure the Chat app

1. Open the [Chat API configuration](https://console.cloud.google.com/apis/api/chat.googleapis.com/hangouts-chat).
2. Fill in app name, avatar, description.
3. Enable **Receive 1:1 messages** and **Join spaces and group conversations**.
4. Set connection settings to **App URL** with `https://your-domain.com/api/webhooks/gchat`.
5. Set visibility, then save.

### 4. Add the bot to a space

1. Open Google Chat.
2. In a Space, open **Manage apps & integrations** then **Add apps** and find your app.

## Advanced

### Pub/Sub for receiving all messages

By default, Google Chat only sends webhooks for @mentions. To receive all messages in a space, set up Workspace Events with Pub/Sub.

```typescript title="lib/bot.ts" lineNumbers
createGoogleChatAdapter({
  pubsubTopic: process.env.GOOGLE_CHAT_PUBSUB_TOPIC,
  impersonateUser: process.env.GOOGLE_CHAT_IMPERSONATE_USER,
});
```

**Topic & subscription:**

1. Under **Pub/Sub** then **Topics**, create a topic (e.g. `chat-events`) and copy its full name to `GOOGLE_CHAT_PUBSUB_TOPIC`.
2. Add `chat-api-push@system.gserviceaccount.com` as a Pub/Sub Publisher.
3. Create a Push subscription with endpoint `https://your-domain.com/api/webhooks/gchat`.

**Domain-wide delegation:**

Required for Workspace Events subscriptions and initiating DMs.

1. In **IAM & Admin** then **Service Accounts**, edit your service account and check **Enable Google Workspace Domain-wide Delegation**. Copy the numeric **Client ID**.
2. In the [Google Admin Console](https://admin.google.com), go to **Security** then **Access and data control** then **API controls**, then **Manage Domain Wide Delegation**.
3. Add the Client ID with these comma-separated scopes:
   ```
   https://www.googleapis.com/auth/chat.spaces.readonly,
   https://www.googleapis.com/auth/chat.messages.readonly,
   https://www.googleapis.com/auth/chat.spaces,
   https://www.googleapis.com/auth/chat.spaces.create
   ```
4. Set `GOOGLE_CHAT_IMPERSONATE_USER` to an admin email.

### Webhook verification

The two transports share one HTTP endpoint, so each verifier only covers its own request shape:

* **Direct webhooks** — Google Chat sends a signed JWT in the `Authorization: Bearer …` header. The expected `aud` claim depends on how the Chat app is configured (see [Verify requests from Google Chat](https://developers.google.com/workspace/chat/verify-requests-from-chat)).
* **Pub/Sub push** — Cloud Pub/Sub sends a signed OIDC JWT whose audience is whatever you configured on the push subscription. Configure with `pubsubAudience`.

If you only configure a direct-webhook verifier, incoming Pub/Sub-shaped requests are rejected with HTTP 401 — and vice versa. Configure both transports if you receive both.

#### Which direct-webhook option do I need?

| Your Chat app                                                                                         | Token type & `aud`                         | Signed by                                                                               | Set                                              |
| ----------------------------------------------------------------------------------------------------- | ------------------------------------------ | --------------------------------------------------------------------------------------- | ------------------------------------------------ |
| Standalone Chat app, **Authentication audience: Project number** (in Chat API config)                 | self-signed JWT, `aud` = project number    | `chat@system.gserviceaccount.com` (its own X.509 certs)                                 | `googleChatProjectNumber`                        |
| Standalone Chat app, **Authentication audience: HTTP endpoint URL**                                   | Google OIDC ID token, `aud` = endpoint URL | Google (`email`: `chat@system.gserviceaccount.com`)                                     | `endpointUrl`                                    |
| **Workspace Add-on Chat app** (built via Google Workspace Marketplace SDK; the audience is hardcoded) | Google OIDC ID token, `aud` = endpoint URL | Google (`email`: `service-{projectNumber}@gcp-sa-gsuiteaddons.iam.gserviceaccount.com`) | `endpointUrl`                                    |
| Mixed across envs / not sure                                                                          | varies                                     | varies                                                                                  | both `googleChatProjectNumber` and `endpointUrl` |

The two token types are verified differently, matching [Google's reference implementation](https://developers.google.com/workspace/chat/verify-requests-from-chat): endpoint-URL tokens are standard OIDC ID tokens checked against Google's public certs plus the Chat service-account `email` claim; project-number tokens are self-signed by `chat@system.gserviceaccount.com` and checked against that service account's own X.509 certificates. When both `googleChatProjectNumber` and `endpointUrl` are set, either token type is accepted. If you don't know which mode your app uses, look at an incoming token: an `email` claim containing `gcp-sa-gsuiteaddons` means it's a Workspace Add-on (URL audience).

<Callout type="info">
  Workspace Add-on Chat apps don't expose an "Authentication audience" radio; their token `aud` is always the endpoint URL. Set `endpointUrl` for these.
</Callout>

### Limitations

* **Typing indicators** — not supported by the Google Chat API.
* **Adding reactions** — the Chat API doesn't allow service-account auth for reactions. With `impersonateUser` configured, the reaction appears as coming from the impersonated user.
* **Message history (`fetchMessages`)** — requires domain-wide delegation with `impersonateUser`.

## Feature support

<FeatureSupport />
