Resources/The Agent API Atlas/Communication/Gmail

Everything an AI agent can do with the Gmail API.

A reference guide for building AI agents: every method, how to authenticate, and the permissions each one needs.

Endpoints37
API versionv1
Last updated22 June 2026
Orientation

How the Gmail API works.

The Gmail API is how an app or AI agent works with a Gmail or Google Workspace mailbox: reading and searching mail, sending and drafting messages, and organising what's there with labels. Access is granted through OAuth and a set of scopes, and an agent only ever reaches what those scopes cover. Gmail can also push a signal whenever the mailbox changes, so an app can react to new mail without checking on a timer.

37Endpoints
8Capability groups
15Read
22Write
9Permissions
Authentication
OAuth 2.0 bearer access tokens, paired with refresh tokens, authenticate user-facing apps; service accounts with domain-wide delegation cover Workspace server-to-server access. All requests go to https://gmail.googleapis.com over HTTPS.
Permissions
Scopes are layered so an app can request only what it needs: gmail.readonly reads mail, gmail.send sends only, gmail.labels manages labels only, gmail.compose covers drafts and sending, gmail.modify reads and writes but cannot permanently delete, gmail.metadata returns headers and labels but no message body, and gmail.settings.basic and gmail.settings.sharing cover settings. Only mail.google.com permits permanent, immediate deletion. Most of these are restricted or sensitive scopes that require Google verification.
Versioning
There is a single stable version, v1, written into the URL path as /gmail/v1/. Backwards-compatible additions go into v1, and Google's deprecation policy gives notice before any breaking change.
Data model
A mailbox is a set of messages, and related messages are grouped into threads. Gmail has no folders: organisation is by labels, where a label is applied to messages and system labels such as INBOX, SENT, SPAM and TRASH act like folders or states. Drafts are unsent messages. The history resource is an incremental change log keyed by an ever-increasing historyId, used for sync and push.
Connect & authenticate

Connection & authentication methods.

An app reaches Gmail over REST, sending HTTPS requests and reading JSON back. Several calls can be bundled into one request to cut round-trips, and Gmail can push a signal when the mailbox changes. Each route is bound by the OAuth scopes the app was granted.

Ways to connect

REST API

An app or AI agent makes direct HTTPS calls to the Gmail API and reads JSON back.

Best forMost integrations.
Governed byAn OAuth access token and the scopes it was granted.
Docs ↗

MCP server

Google hosts a remote Model Context Protocol server for Gmail at gmailmcp.googleapis.com that exposes Gmail to MCP-aware agents, such as Claude and Google Antigravity, as standard tools. It is in Google Workspace Developer Preview.

Best forAgents that speak MCP and want tool-calling without writing raw HTTP.
Governed byThe authorising user's OAuth scopes; the server inherits the same permissions and data-governance controls as the API.
Docs ↗

Batch HTTP requests

Several Gmail calls are bundled into one HTTP request to cut round-trips.

Best forCutting round-trips on bulk work.
Governed byThe same token and scopes; each inner call still costs its own quota.
Docs ↗

Push notifications (watch + Cloud Pub/Sub)

Gmail pushes a mailbox-change signal to a Cloud Pub/Sub topic the app owns.

Best forReacting to new mail without polling.
Governed byA read scope plus a Cloud Pub/Sub topic the app owns.
Docs ↗
Authentication

OAuth 2.0

OAuth 2.0 is the standard path, with a signed-in user granting an app access to their mailbox. The restricted scopes (readonly, modify, compose, mail.google.com, metadata, insert) require Google app verification and, for production, a CASA security assessment.

TokenAccess token (bearer) + refresh token
Best forUser-facing apps acting on behalf of a signed-in Gmail or Workspace user.
Docs ↗

Service account (domain-wide delegation)

A service account with domain-wide delegation works across a Google Workspace organisation but not consumer Gmail. A Workspace admin grants the service account's client ID the chosen scopes in the Admin console, and the app then impersonates any user in the domain.

TokenSigned JWT exchanged for an access token, impersonating a user
Best forGoogle Workspace server-to-server access across an org's mailboxes without per-user consent.
Docs ↗
Capability map

What an AI agent can do in Gmail.

Gmail's API is divided into areas that map to parts of a mailbox: messages and the threads that group them, labels, drafts, the history change log, attachments, account settings, and push notifications. Each area carries its own scopes, and some reach further than others.

Endpoint reference

Every Gmail API method.

Filter by method, access, or permission, or search any path. Select a row for version detail, rate limits, the related webhook event, and the source.

MethodEndpointWhat it doesAccessPermissionVersion

Messages

Read, send, label, trash and delete messages.11

Also satisfied by gmail.modify, gmail.metadata (metadata returns no body), or mail.google.com.

Acts onmessage
Permission (capability)gmail.readonly
VersionAvailable since the API’s base version
Webhook eventNone
Rate limit5 quota units

The metadata format works with gmail.metadata; full and raw need gmail.readonly or broader.

Acts onmessage
Permission (capability)gmail.readonly
VersionAvailable since the API’s base version
Webhook eventNone
Rate limit20 quota units

Minimal scope is gmail.send; also gmail.compose, gmail.modify, mail.google.com.

Acts onmessage
Permission (capability)gmail.send
VersionAvailable since the API’s base version
Webhook eventmessagesAdded
Rate limit100 quota units

gmail.insert (also gmail.modify, mail.google.com).

Acts onmessage
Permission (capability)gmail.insert
VersionAvailable since the API’s base version
Webhook eventmessagesAdded
Rate limit25 quota units

gmail.insert (also gmail.modify, mail.google.com).

Acts onmessage
Permission (capability)gmail.insert
VersionAvailable since the API’s base version
Webhook eventmessagesAdded
Rate limit25 quota units

gmail.modify (or mail.google.com).

Acts onmessage
Permission (capability)gmail.modify
VersionAvailable since the API’s base version
Webhook eventlabelsAdded
Rate limit5 quota units

gmail.modify (or mail.google.com).

Acts onmessage
Permission (capability)gmail.modify
VersionAvailable since the API’s base version
Webhook eventmessagesDeleted
Rate limit20 quota units

gmail.modify (or mail.google.com).

Acts onmessage
Permission (capability)gmail.modify
VersionAvailable since the API’s base version
Webhook eventNone
Rate limit5 quota units

Permanent delete requires full-access mail.google.com only.

Acts onmessage
Permission (capability)mail.google.com
VersionAvailable since the API’s base version
Webhook eventmessagesDeleted
Rate limit10 quota units

gmail.modify (or mail.google.com).

Acts onmessage
Permission (capability)gmail.modify
VersionAvailable since the API’s base version
Webhook eventlabelsAdded
Rate limit50 quota units

Permanent delete requires full-access mail.google.com only.

Acts onmessage
Permission (capability)mail.google.com
VersionAvailable since the API’s base version
Webhook eventmessagesDeleted
Rate limit50 quota units

Threads

Read and act on whole conversations at once.5

Also gmail.modify, gmail.metadata, mail.google.com.

Acts onthread
Permission (capability)gmail.readonly
VersionAvailable since the API’s base version
Webhook eventNone
Rate limit10 quota units

Also gmail.modify, gmail.metadata, mail.google.com.

Acts onthread
Permission (capability)gmail.readonly
VersionAvailable since the API’s base version
Webhook eventNone
Rate limit40 quota units

gmail.modify (or mail.google.com).

Acts onthread
Permission (capability)gmail.modify
VersionAvailable since the API’s base version
Webhook eventlabelsAdded
Rate limit10 quota units

gmail.modify (or mail.google.com).

Acts onthread
Permission (capability)gmail.modify
VersionAvailable since the API’s base version
Webhook eventmessagesDeleted
Rate limit20 quota units

Permanent delete requires full-access mail.google.com only.

Acts onthread
Permission (capability)mail.google.com
VersionAvailable since the API’s base version
Webhook eventmessagesDeleted
Rate limit20 quota units

Labels

Create, read, update and delete labels.5

Also gmail.labels, gmail.modify, gmail.metadata, mail.google.com.

Acts onlabel
Permission (capability)gmail.readonly
VersionAvailable since the API’s base version
Webhook eventNone
Rate limit1 quota units

Also gmail.labels, gmail.modify, gmail.metadata, mail.google.com.

Acts onlabel
Permission (capability)gmail.readonly
VersionAvailable since the API’s base version
Webhook eventNone
Rate limit1 quota units

gmail.labels (also gmail.modify, mail.google.com).

Acts onlabel
Permission (capability)gmail.labels
VersionAvailable since the API’s base version
Webhook eventNone
Rate limit5 quota units

gmail.labels (also gmail.modify, mail.google.com). A PATCH variant exists for partial update.

Acts onlabel
Permission (capability)gmail.labels
VersionAvailable since the API’s base version
Webhook eventNone
Rate limit5 quota units

gmail.labels (also gmail.modify, mail.google.com).

Acts onlabel
Permission (capability)gmail.labels
VersionAvailable since the API’s base version
Webhook eventNone
Rate limit5 quota units

Drafts

Create, read, update, send and delete drafts.6

Also gmail.compose, gmail.modify, mail.google.com.

Acts ondraft
Permission (capability)gmail.readonly
VersionAvailable since the API’s base version
Webhook eventNone
Rate limit5 quota units

Also gmail.compose, gmail.modify, mail.google.com.

Acts ondraft
Permission (capability)gmail.readonly
VersionAvailable since the API’s base version
Webhook eventNone
Rate limit20 quota units

gmail.compose (also gmail.modify, mail.google.com).

Acts ondraft
Permission (capability)gmail.compose
VersionAvailable since the API’s base version
Webhook eventNone
Rate limit10 quota units

gmail.compose (also gmail.modify, mail.google.com).

Acts ondraft
Permission (capability)gmail.compose
VersionAvailable since the API’s base version
Webhook eventNone
Rate limit15 quota units

gmail.compose (also gmail.modify, mail.google.com). gmail.send alone does not cover drafts.send.

Acts ondraft
Permission (capability)gmail.compose
VersionAvailable since the API’s base version
Webhook eventNone
Rate limit100 quota units

gmail.compose (also gmail.modify, mail.google.com).

Acts ondraft
Permission (capability)gmail.compose
VersionAvailable since the API’s base version
Webhook eventNone
Rate limit10 quota units

History

Track incremental mailbox changes since a point in time.1

Also gmail.modify, gmail.metadata, mail.google.com. Drives polling after a push notification.

Acts onhistoryRecord
Permission (capability)gmail.readonly
VersionAvailable since the API’s base version
Webhook eventNone
Rate limit2 quota units

Attachments

Fetch attachment bodies from a message.1

gmail.readonly (also gmail.modify, mail.google.com). The attachment ID comes from messages.get.

Acts onmessagePartBody
Permission (capability)gmail.readonly
VersionAvailable since the API’s base version
Webhook eventNone
Rate limit20 quota units

Settings

Read and change mail settings: filters, vacation auto-reply, send-as aliases and delegates.5

gmail.settings.basic (also gmail.readonly, gmail.modify, mail.google.com).

Acts onsetting
Permission (capability)gmail.settings.basic
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

gmail.settings.basic (or mail.google.com).

Acts onsetting
Permission (capability)gmail.settings.basic
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

gmail.settings.basic (or mail.google.com).

Acts onsetting
Permission (capability)gmail.settings.basic
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

gmail.settings.basic (also gmail.readonly, gmail.modify, mail.google.com).

Acts onsetting
Permission (capability)gmail.settings.basic
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

gmail.settings.sharing (restricted; admin and domain-wide delegation use only). Also mail.google.com.

Acts onsetting
Permission (capability)gmail.settings.sharing
VersionAvailable since the API’s base version
Webhook eventNone
Rate limitStandard limits apply

Users / Watch

Read the profile and control push notifications.3

Any Gmail read scope works (gmail.readonly, gmail.modify, gmail.metadata, mail.google.com).

Acts onuser
Permission (capability)gmail.readonly
VersionAvailable since the API’s base version
Webhook eventNone
Rate limit1 quota units

gmail.readonly (or any broader read scope). Returns historyId and expiration.

Acts onuser
Permission (capability)gmail.readonly
VersionAvailable since the API’s base version
Webhook eventNone
Rate limit100 quota units

gmail.readonly (or any broader read scope).

Acts onuser
Permission (capability)gmail.readonly
VersionAvailable since the API’s base version
Webhook eventNone
Rate limit50 quota units
No endpoints match those filters.
Webhooks

Webhook events.

Gmail sends a single mailbox-change signal to a Cloud Pub/Sub topic an app owns rather than a detailed event for each change. The signal carries a historyId, and the app reads the history change log from its last known point to find exactly what changed. The change types below are what the history log reports.

EventWhat it signalsTriggered by
messagesAddedA message was added to the mailbox./gmail/v1/users/{userId}/messages/send
/gmail/v1/users/{userId}/messages
/gmail/v1/users/{userId}/messages/import
messagesDeletedA message was removed from the mailbox./gmail/v1/users/{userId}/messages/{id}
/gmail/v1/users/{userId}/messages/{id}/trash
/gmail/v1/users/{userId}/messages/batchDelete
/gmail/v1/users/{userId}/threads/{id}/trash
/gmail/v1/users/{userId}/threads/{id}
labelsAddedA label was added to a message./gmail/v1/users/{userId}/messages/{id}/modify
/gmail/v1/users/{userId}/messages/batchModify
/gmail/v1/users/{userId}/threads/{id}/modify
labelsRemovedA label was removed from a message./gmail/v1/users/{userId}/messages/{id}/modify
/gmail/v1/users/{userId}/messages/batchModify
/gmail/v1/users/{userId}/threads/{id}/modify
No events match that search.
Rate limits & pagination

Rate limits, pagination & request size.

Gmail meters how fast an app can call the API and how much mail an account can send. Request rate is measured in quota units, an abstract cost that varies by method, and sending is capped separately by account policy.

Request rate

Gmail meters requests in quota units, an abstract cost that varies by method (a send costs 100 units, a list costs 5). Each method's cost is shown on its row. The default per-user limit is about 6,000 units per minute (the 2015 release notes cite 250 units per second), inside a larger per-project ceiling. Going over returns an HTTP 429, or a 403 rateLimitExceeded, so an app should back off and retry with jitter. Mail sending is capped separately by account policy, covered under request size below.

Pagination

List methods page through results with pageToken and maxResults. A response carries a nextPageToken, which is passed back as the pageToken for the next page. For messages.list and threads.list, maxResults defaults to 100 and tops out at 500.

Request size

messages.import accepts a message up to 150 MB. A standard send tops out at roughly 35 MB once MIME-encoded, a figure that is widely documented but not stated on the v1 messages.send reference page. A single message can address up to 500 unique recipients through the API. Separately, account policy caps sending at roughly 500 messages per day on consumer Gmail and roughly 2,000 messages per day, with roughly 10,000 recipients per day, on Google Workspace. These caps are account or Workspace policy rather than API quota, counted over a rolling 24-hour window.

Errors

Status codes & error handling.

The status codes an agent should handle, and what to do about each.

StatusCodeMeaningWhat to do
400badRequest / invalidArgumentThe request is malformed: a required field is missing, a value is invalid, an attachment is bad, or the raw message is malformed.Fix the request per the error message and do not retry it unchanged, as it is not retriable.
400failedPreconditionThe request cannot run in the current state, because a precondition such as a required mailbox state is not met.Resolve the precondition, often by re-fetching state, before retrying.
401authError (Invalid Credentials)The access token has expired, is invalid, or is missing the required scope.Refresh the access token with the refresh token, and if a scope is missing, re-run OAuth consent. Retry once after the refresh.
403rateLimitExceeded / userRateLimitExceededThe per-user or per-project request-rate quota has been exceeded.Slow down and retry with exponential backoff and jitter, smoothing bursts to stay under 250 units per user per second.
403dailyLimitExceededThe project's daily API quota has been reached.Reduce usage or request a quota increase in the Cloud Console, since a simple retry will not fix it.
403domainPolicyA Workspace admin has disabled API or Gmail-app access for the domain.The user must contact their Workspace admin to enable access, as the app cannot retry past this.
404notFoundThe requested message, thread, label, or draft ID does not exist or is not visible to this user.Verify the ID and the userId or impersonated user, and do not retry unchanged.
429tooManyRequestsPer-user limits on mail sending, bandwidth, or concurrent requests have been exceeded.Back off and retry with exponential backoff and jitter, and reduce concurrency.
500backendErrorA transient server-side error occurred.Retry with exponential backoff, as this is retriable.
503backendError / unavailableThe service is temporarily unavailable.Retry with exponential backoff, as this is retriable.
Versioning & freshness

Version history.

Gmail's API is at v1, with the version written into the URL path. New capabilities are added to v1 rather than starting a new version.

Version history

What changed, and when

Latest versionv1
v1Current version
Gmail API v1

Gmail's API is at v1 and stable, versioned in the URL path at /gmail/v1/. New capabilities are added to v1 rather than minting a new version, and Google's deprecation policy gives notice before any breaking change. The dated entries below are notable changes from the release notes.

What changed
  • The current and only public version
  • Backwards-compatible additions ship into v1
2026-05-01Feature update
Quota costs adjusted

Google changed the quota-unit cost of several read and trash methods under a new quota model.

What changed
  • Costs changed for drafts.get, messages.get, messages.attachments.get, messages.trash, threads.get and threads.trash
2026-04-22Feature update
MCP server (developer preview)

Google launched a Model Context Protocol server for Gmail in developer preview, exposing Gmail to MCP-aware agents as standard tools.

What changed
  • A hosted MCP server lets agents call Gmail without writing raw HTTP
2016-07-01Feature update
Settings endpoints added

Endpoints for managing mail settings were added.

What changed
  • New settings for send-as aliases, signatures, forwarding, filters, the vacation responder, and POP/IMAP
2015-05-29Feature update
Push notifications added

Push notifications arrived through Cloud Pub/Sub.

What changed
  • users.watch and users.stop publish mailbox-change events to a Pub/Sub topic, with label filtering
2015-03-31Feature update
New OAuth scopes

Two scopes were introduced for finer-grained access.

What changed
  • New scopes: gmail.insert and gmail.labels
2015-01-15Feature update
Per-user quota raised

The default per-user request quota was raised tenfold.

What changed
  • Per-user limit raised from 25 to 250 quota units per second

v1 is the only version. New features arrive in v1, and Google's deprecation policy gives advance notice before any breaking change, so the release notes are where additions and changes are announced.

Gmail API release notes ↗
Questions

Gmail API, answered.

Which OAuth scope should I request, and will my app need verification?+
Request the narrowest scope that covers the calls an app makes: gmail.readonly to read, gmail.send to send only, gmail.labels for labels, gmail.modify for read and write without permanent delete, and mail.google.com only where permanent deletion is required. Most Gmail scopes are restricted or sensitive, so a production app needs Google's OAuth verification and, for restricted scopes, an annual third-party CASA security assessment.
What are the sending limits?+
The API request-rate quota, 250 units per user per second with a send costing 100 units, is separate from the mailbox sending caps. Sending caps are account policy: roughly 500 messages per day on consumer Gmail and 2,000 messages per day on Google Workspace, with up to 500 recipients per message through the API. Exceeding a cap returns a 4xx error, and the caps reset over a rolling 24-hour window.
Should I poll or use push notifications, and how does history work?+
Push notifications avoid polling: a call to users.watch registers a Cloud Pub/Sub topic, and Gmail then publishes one mailbox-changed event carrying the new historyId. An app reacts by calling users.history.list with its last known startHistoryId to fetch exactly what changed, and renews the watch within 7 days. Polling history.list on a timer is the fallback, and full re-listing of messages costs far more for the same result.
How do labels work, and are they folders?+
Gmail has no folders, so everything is labels, and a single message can carry several at once. System labels (INBOX, SENT, DRAFT, SPAM, TRASH, UNREAD, STARRED, IMPORTANT, and the CATEGORY labels) behave like folders or flags, and user-created labels organise mail. Mail is moved or filed by adding and removing labels through messages.modify or threads.modify, or in bulk through batchModify.
How do I read attachments?+
A messages.get call reads the message structure, and each attachment part carries an attachmentId. A messages.attachments.get call with that ID then fetches the attachment body, returned base64url-encoded. Small attachment bodies may sit inline in the message payload, while larger ones must be fetched by attachmentId.
How do I make many calls efficiently, and is there a batch API?+
A batch HTTP request sent to /batch/gmail/v1 bundles multiple operations into one round-trip, and the dedicated bulk endpoints messages.batchModify and messages.batchDelete handle label changes and permanent deletes across many IDs. Batching saves HTTP overhead, but each inner operation still consumes its own quota units and is rate-limited.
Can I access Gmail across my whole Workspace org without each user clicking 'allow'?+
A service account using domain-wide delegation makes this possible. A Workspace admin authorises the service account's client ID for the required Gmail scopes in the Admin console, and the app then impersonates any user in the domain to call the API. This works only for Google Workspace accounts, not consumer Gmail, and the admin can scope or revoke it centrally.
What is Bollard AI?

Control what every AI agent can do in Gmail.

Bollard AI sits between a team's AI agents and Gmail. Grant each agent exactly the access it needs, read or send, label by label, and every call is checked and logged.

  • Set read, send or full access per agent, never a shared inbox password.
  • Denied by default, so an agent reaches only what's been explicitly allowed.
  • Every call recorded in plain English: who, what, where, and the decision.
Gmail
Inbox Agent
Read inbox MailboxOffReadFull use
Send mail ActionOffReadFull use
Invoices label LabelOffReadFull use
Per-agent access, set in Bollard AI, not in Gmail