Connect to Gmail
Connect Gmail to Retool to read, send, and manage email using the Gmail API.
Gmail is Google's email service for sending, receiving, and organizing messages. Retool connects to Gmail through the Gmail API v1 using either OAuth 2.0 or a Google service account.
After you create a Gmail resource in Retool, you can:
- List and search messages in a mailbox and display them in tables or lists.
- Read message content, headers, and attachments for triage or summarization apps.
- Send messages and create drafts from forms and other user inputs.
- Apply or remove labels, move messages to trash, and restore trashed messages.
- List labels and inspect mailbox profile metadata.
Before you begin
To connect Gmail to Retool, you need the following:
- Cloud instances
- Self-hosted instances
- Google account: A Google account or Google Workspace user with access to the mailbox you want to query.
- Retool permissions: Edit all permissions for resources in your organization.
- Google account: A Google account or Google Workspace user with access to the mailbox you want to query.
- Custom OAuth 2.0 client: A Google OAuth 2.0 client configured for your Retool instance. Self-hosted instances cannot use Retool's hosted OAuth app and must provide their own client ID and secret. Service account authentication does not require an OAuth client.
- Network access: Your Retool instance must be able to reach
accounts.google.com,oauth2.googleapis.com, andgmail.googleapis.comover HTTPS. - Retool permissions: Edit all permissions for resources in your organization.
Create a Gmail resource
Follow these steps to create a Gmail resource in your Retool organization.
1. Create a new resource
In your Retool organization, navigate to Resources in the main navigation and click Create new → Resource. Search for Gmail and click the Gmail tile to begin configuration.
Use folders to organize your resources by team, environment, or data source type. This helps keep your resource list manageable as your organization grows.
2. Configure general settings
Specify a name and description for the resource that indicates which Google account or workspace it connects to. The description provides more context to users and Assist about how to use the resource.
| Example name | Example description |
|---|---|
Gmail | Default Gmail resource for the support team. Reads inbox threads and sends replies from internal apps. |
Gmail (read only) | Read-only Gmail resource for displaying recent messages on dashboards. |
When using Retool's hosted OAuth app (Cloud) or a custom OAuth app (self-hosted), you typically only need one resource. Each user authenticates individually and can only access their own mailbox. Creating multiple resources is usually unnecessary unless you need to support multiple OAuth applications or mix OAuth with service account authentication.
3. Configure authentication
Configure the connection settings for your Gmail resource under the Credentials section of the resource configuration form.

Gmail resource configuration form.
Authentication
Gmail supports two authentication methods. Choose based on whether queries should run as the signed-in user or as a non-interactive service identity.
| Authentication method | Use cases |
|---|---|
| OAuth 2.0 | Interactive apps where each user authenticates with their own Google account. Each user only sees their own mailbox. |
| Google Service Account | Automated workflows, scheduled queries, and shared internal apps that need to act as a non-interactive service identity. For Gmail, service accounts typically require domain-wide delegation in Google Workspace so the service account can impersonate a user mailbox. |
- Cloud instances
- Self-hosted instances
option A: OAuth 2.0 with Retool's hosted app (recommended)
Retool provides a hosted OAuth 2.0 client for Cloud organizations, so no external configuration is required.
- Select OAuth 2.0 as the Authentication method.
- Choose the Type:
- Read only—queries can read mailbox metadata and message content.
- Read and write—queries can read, modify labels, insert messages, and send or update mailbox data allowed by the modify scopes.
- Optionally enable Share credentials between users to allow all users of the resource to share a single set of credentials. By default, each user authenticates individually.
- Click Connect with OAuth and authorize Retool to access your Gmail.
- Click Create resource to save.
option B: Google service account
Use a service account when queries should run as a non-interactive service identity rather than as the signed-in user.
- Create a service account in the Google Cloud Console and generate a JSON key.
- Enable the Gmail API for your Google Cloud project and configure domain-wide delegation for the service account with the Gmail scopes your apps need.
- In Retool, select Google Service Account as the Authentication method.
- Choose the Type: Read only or Read and write.
- Paste the JSON contents of your service account key into the Service account key field.
- Click Create resource to save.
Refer to Google's service account documentation for setup details and key rotation guidance.
option A: OAuth 2.0 with a custom app (recommended)
Self-hosted instances must provide their own Google OAuth 2.0 client. Retool's hosted OAuth app is only available for Cloud organizations.
- Create an OAuth 2.0 client in the Google Cloud Console and configure the authorized redirect URI for your Retool instance.
- In Retool, select OAuth 2.0 as the Authentication method.
- Enter the Client ID and Client secret from your OAuth 2.0 client.
- Choose the Type:
- Read only—queries can read mailbox metadata and message content.
- Read and write—queries can read, modify labels, insert messages, and send or update mailbox data allowed by the modify scopes.
- Optionally enable Share credentials between users to allow all users of the resource to share a single set of credentials.
- Click Connect with OAuth and authorize Retool to access your Gmail.
- Click Create resource to save.
option B: Google service account
Use a service account when queries should run as a non-interactive service identity rather than as the signed-in user. Service accounts do not require a custom OAuth client.
- Create a service account in the Google Cloud Console and generate a JSON key.
- Enable the Gmail API for your Google Cloud project and configure domain-wide delegation for the service account with the Gmail scopes your apps need.
- In Retool, select Google Service Account as the Authentication method.
- Choose the Type: Read only or Read and write.
- Paste the JSON contents of your service account key into the Service account key field.
- Click Create resource to save.
Type
The Type setting controls the OAuth scopes used for Gmail API calls.
| Type | API access |
|---|---|
| Read only | Read mailbox metadata and message content. Uses the gmail.metadata and gmail.readonly scopes. Use for apps that list, search, or display email. |
| Read and write | Read and write access for labels, inserts, and mailbox modifications. Uses the gmail.labels, gmail.insert, and gmail.modify scopes. Use for apps that send mail, manage drafts, apply labels, or trash messages. |
To change the Type after a resource has been created, update the authentication settings and re-authorize the resource. Users are prompted to re-consent on the next query.
- Cloud instances
Outbound region
By default, requests originate from your organization's outbound region (for example, us-west-2). Enable Override default outbound Retool region to route requests through a different region. This is useful when Gmail API access is restricted by IP or when you need to align with data residency requirements.
4. Save the resource
Click Create resource to save your Gmail resource.
Gmail resources cannot be tested from the resource configuration screen. Save the resource and verify the connection by running a query—for example, get the authenticated user's profile with /users/{userId}/profile GET and set userId to me.
Query Gmail data
Once you've created a Gmail resource, you can query it in apps, workflows, and agent tools. Gmail queries call the Gmail API v1—Retool exposes an Operation dropdown listing the available Gmail endpoints.
Create a query
You can create a Gmail query using Assist to generate queries with natural language, or manually by selecting an operation.
- Assist
- Code
Use Assist to generate queries from natural language prompts.
To create a query with Assist:
- In the Retool app IDE, click the Assist button at the bottom of the left toolbar to open the Assist panel.
- Write a prompt describing the data you want to retrieve or the operation you want to perform, referencing your resource using
@. - Press Enter to submit the prompt.
- Select your Gmail resource when prompted.
- Review the generated query and click Run query to add it to your app.
To manually create a Gmail query in a Retool app:
- In the Retool app IDE, open the Code tab, then click + in the page or global scope.
- Select Resource query.
- Choose your Gmail resource.
- Select an Operation from the dropdown. Operations are labeled by endpoint path and HTTP method (for example,
/users/{userId}/messages GET). - Configure the required parameters and run the query.
Query configuration fields
The fields below describe the Retool-side configuration—for the full list of available endpoints and parameters, refer to the Gmail API reference.
Operation
Select a Gmail API endpoint from the dropdown. Each entry is labeled by endpoint path and HTTP method.
# Get the authenticated user's profile
/users/{userId}/profile GET
# List messages in a mailbox
/users/{userId}/messages GET
# Get a message
/users/{userId}/messages/{id} GET
# Send a message
/users/{userId}/messages/send POST
# Trash a message
/users/{userId}/messages/{id}/trash POST
# List labels
/users/{userId}/labels GET
Path parameters (like userId and id), URL parameters, and a request body appear once an operation is selected. Use me as the userId to target the authenticated user's mailbox.
URL parameters
Common URL parameters for message list and get operations:
| Parameter | Description | Example |
|---|---|---|
q | Gmail search query using the same syntax as the Gmail search box. | is:unread newer_than:7d |
labelIds | Only return messages with the given label IDs. | INBOX |
maxResults | Maximum number of messages to return per page. | 50 |
pageToken | Token from a previous list response for pagination. | {{ listMessagesQuery.data.nextPageToken }} |
includeSpamTrash | Include messages from SPAM and TRASH. | false |
format | Message detail level for get operations: minimal, full, raw, or metadata. | full |
Request body
For write operations (POST, PUT, PATCH), provide a JSON body matching the Gmail API resource schemas. Use embedded expressions to interpolate values from app state.
Sending mail requires a raw field containing a base64url-encoded RFC 2822 message. Refer to Google's Gmail API sending guide for the expected format. Encode the message as UTF-8 bytes before base64url-encoding—do not pass the string directly to btoa(), which throws on characters outside Latin-1.
{
"raw": {{
(() => {
const message = [
`To: ${form1.data.to}`,
`Subject: ${form1.data.subject}`,
`Content-Type: text/plain; charset="UTF-8"`,
"",
form1.data.body
].join("\r\n");
const bytes = new TextEncoder().encode(message);
let binary = "";
bytes.forEach((byte) => {
binary += String.fromCharCode(byte);
});
return btoa(binary)
.replace(/\+/g, "-")
.replace(/\//g, "_")
.replace(/=+$/, "");
})()
}}
}
Advanced
Use the Advanced section to add request headers or URL parameters not covered by the operation's defaults. The Authorization header is set automatically from the resource's authentication.
Gmail query examples
These examples demonstrate the most common Gmail operations in Retool apps. For a complete reference of available operations and parameters, refer to the Gmail API documentation.
list recent inbox messages
Create a query named listMessagesQuery to list recent messages in the authenticated user's inbox.
Configure the query:
| Field | Value |
|---|---|
| Operation | /users/{userId}/messages GET |
| userId (path) | me |
| URL parameters | q=in:inbox newer_than:14dmaxResults=50 |
The list response returns message IDs and thread IDs only. Create a second query (or use Assist) to fetch full message details with /users/{userId}/messages/{id} GET for each selected row.
Add a Table component and set its Data property to {{ listMessagesQuery.data.messages }}.
get a message
Create a query named getMessageQuery to load the full content of a selected message.
Configure the query:
| Field | Value |
|---|---|
| Operation | /users/{userId}/messages/{id} GET |
| userId (path) | me |
| id (path) | {{ table1.selectedRow.data.id }} |
| URL parameters | format=full |
Message bodies are returned in payload.parts (multipart) or payload.body.data (single part), usually as base64url-encoded content. Decode with JavaScript transformers before displaying in a Text component.
send an email from a form
Add a Form component with inputs for the recipient, subject, and body.
Create a query named sendMessageQuery to send a new message.
Configure the query:
| Field | Value |
|---|---|
| Operation | /users/{userId}/messages/send POST |
| userId (path) | me |
Set the Request body to a JSON object with a base64url-encoded raw RFC 2822 message, as shown in Request body.
Add an event handler to the form's Submit event that runs sendMessageQuery and shows a success notification with the new message ID from {{ sendMessageQuery.data.id }}.
trash a message
Create a query named trashMessageQuery to move a message to the trash.
Configure the query:
| Field | Value |
|---|---|
| Operation | /users/{userId}/messages/{id}/trash POST |
| userId (path) | me |
| id (path) | {{ table1.selectedRow.data.id }} |
Add a Button with a Click event handler that opens a confirmation modal and, on confirm, runs trashMessageQuery and reruns listMessagesQuery to refresh the table.
list labels
Create a query named listLabelsQuery to populate a label picker with the labels in the authenticated user's mailbox.
Configure the query:
| Field | Value |
|---|---|
| Operation | /users/{userId}/labels GET |
| userId (path) | me |
Bind a Select component's options to {{ listLabelsQuery.data.labels }}, with the Label key set to name and the Value key set to id. Use the selected label ID in message list queries via the labelIds URL parameter.
Best practices
Follow these best practices to optimize performance, maintain security, and ensure data integrity when working with REST APIs.
Performance
- Cache responses: For data that doesn't change frequently, enable query caching to reduce API calls and improve response times.
- Use pagination: Implement pagination for endpoints that return large datasets to reduce payload size and improve performance.
- Batch requests: When available, use batch API endpoints to combine multiple operations into a single request.
- Minimize payload size: Request only the fields you need using query parameters or API-specific field selection features.
- Set appropriate timeouts: Configure query timeouts based on expected API response times to prevent hung requests.
Security
- Use configuration variables: Store API keys and tokens in configuration variables or secrets rather than hardcoding them.
- Use HTTPS only: Always connect to APIs over HTTPS to encrypt data in transit and protect authentication credentials.
- Rotate credentials regularly: Follow your API provider's recommendations for credential rotation and key management.
- Validate SSL certificates: Keep SSL certificate verification enabled unless absolutely necessary for development environments.
- Use resource environments: Configure multiple resource environments to maintain separate API configurations for production, staging, and development.
- Apply least privilege: Use API keys with minimal required permissions. Create separate keys for different environments.
Data integrity
- Validate user input: Sanitize and validate all user input before including it in API requests to prevent injection attacks.
- Handle errors gracefully: Configure error notifications and fallback behavior for failed API calls to improve user experience.
- Use idempotency keys: For APIs that support idempotency keys, include them in POST/PATCH requests to prevent duplicate operations.
- Verify responses: Check response status codes and validate response data structure before using it in your app.
- Implement retry logic: For transient failures, use Retool's automatic retry settings or implement custom retry logic with exponential backoff.
Gmail-specific considerations
- Choose the narrowest scope: Use the Read only type unless your app needs to send mail, manage drafts, or modify labels. Switching from a broader scope to a narrower one later forces every user to re-consent.
- Use
mefor the signed-in user's mailbox: For apps that operate on the current user's mailbox, setuserIdtomeinstead of looking up the email address first. - List endpoints return IDs only:
messages.listreturns message and thread IDs. Callmessages.get(or batch requests) when you need headers, snippets, or body content. - Encode outbound mail as
rawRFC 2822: The send and draft APIs expect a base64url-encoded MIME message in therawfield. Build the headers and body in JavaScript, UTF-8-encode withTextEncoder, then convert to base64url. Do not callbtoa()on the string directly—it fails on non–Latin-1 characters. - Prefer trash over permanent delete: Use
messages.trashfor recoverable deletion. Permanent delete cannot be undone and requires broader privileges than the default modify scopes allow. - Configure domain-wide delegation for service accounts: Unlike Drive-based Google products, Gmail access with a service account usually requires Workspace domain-wide delegation to impersonate a user mailbox.
Related resources
Google OAuth credentials
Set up a custom Google OAuth 2.0 client for self-hosted Retool.
Connect to Google Calendar
Schedule and manage events alongside email workflows.
Connect to Google Sheets
Sync message data with spreadsheets for reporting.
Create a resource
Learn how to create and manage resources in Retool.
Gmail API reference
Full reference for the Gmail API v1 endpoints and parameters.
Retool community: Gmail
Community discussions and solutions for Gmail integrations.