Search + K

Command Palette

Search for a command to run...

Sign In

Gmail organizes mail and user preferences around a single user (use the special value me for the authenticated account) and a small set of core resources: messages, threads, drafts, labels, attachments, and settings (filters, forwarding, send-as aliases, IMAP/POP, vacation, delegates, client-side encryption). Many operations are simple CRUD against those resource IDs; knowing where to get each ID and which operation changes state is the most important operational knowledge.

How the domain is modeled

Gmail treats mail at two granularities: individual messages and grouped threads. Labels attach to messages and threads. A draft contains a message that can be updated or sent. Attachments live inside a message’s payload parts and are referenced by an id inside the message. Settings and identity resources (filters, forwarding addresses, sendAs aliases, S/MIME info, client-side-encryption identity/keypair entries) are separate resources identified by email addresses or resource IDs.

Key relationships you will use repeatedly:

  • Most mailbox operations are scoped to a user via userId (commonly me).
  • messages.list and threads.list are the canonical ways to obtain messageId and threadId values for later calls.
  • Labels are created/listed via labels.list/labels.create and their id values are used in messages.list/messages.modify/threads.modify and filtering parameters.
  • Attachments: fetch the message first (message payload includes attachment metadata and attachment id), then call the attachment retrieval operation with that messageId + attachment id.

IDs and entry points

Start by listing the resource that naturally provides the ID you need. Common entry points:

  • To act on mail: users.messages.list → get messageId; users.threads.list → get threadId.
  • To operate on drafts: users.drafts.list → get draftId; users.drafts.create returns the new Draft.
  • To change labels or find label IDs: users.labels.list → get labelId used by messages.modify, threads.modify, and list filters.
  • To read inbox state and incremental updates: users.getProfile (for account metadata) and users.history.list (requires a valid startHistoryId obtained from message/thread historyId or from previous responses).
  • To manage send aliases and cryptographic identities: users.settings.sendAs.list, users.settings.cse.identities.list, and users.settings.cse.keypairs.list.

Always check the list operation that logically contains the resource you need—most operations require those IDs and do not create them implicitly.

Common tasks and the sequences that accomplish them

Each sequence below uses the resource names and parameters shown in the operation signatures.

Read a message or thread

  • Use users.messages.get (or users.threads.get for all messages in a thread). Choose format:
    • full to get payload, headers, and parts.
    • metadata with metadataHeaders to fetch only specific headers.
    • raw to retrieve the raw message object as stored (useful when you need MIME source).
  • To find attachments: inspect the message payload parts for parts with an attachmentId. Call the attachment retrieval operation with messageId + id.

Search and list mail

  • Use users.messages.list or users.threads.list with q (Gmail search syntax) or labelIds. The response returns IDs only; call users.messages.get to fetch full content for any IDs returned.
  • includeSpamTrash controls whether SPAM/TRASH are included. Note that q cannot be used with the gmail.metadata scope.

Send mail

  • To deliver mail immediately, call users.messages.send with a Message payload (the raw field is the typical carrier for a full MIME message). messages.send actually transmits the message.
  • To prepare and send later: create or update a draft (users.drafts.create / users.drafts.update) and then call users.drafts.send to send that draft.
  • For migrations or injecting mail into a mailbox (without sending): use users.messages.insert or users.messages.import. import exposes flags like neverMarkSpam, processForCalendar, and internalDateSource for preserving original timestamps or handling calendar invites.

Modify labels and message state

  • To add/remove labels on a single message use users.messages.modify (pass addLabelIds and/or removeLabelIds). For threads, use users.threads.modify.
  • For bulk operations: users.messages.batchModify accepts a list of message IDs. users.messages.batchDelete deletes multiple messages at once.
  • To move a message to Trash use users.messages.trash; to remove from Trash use users.messages.untrash. users.messages.delete permanently removes the message.

Manage drafts

  • Create: users.drafts.create returns a Draft with an id.
  • Update an existing draft: users.drafts.update using that id.
  • Send a draft: users.drafts.send (you can also send a freshly created draft directly).
  • Delete: users.drafts.delete.

Threads

  • Use users.threads.get to fetch an entire thread.
  • Modify thread labels with users.threads.modify.
  • Delete vs Trash: users.threads.delete permanently deletes; users.threads.trash moves to Trash and untrash restores it.

Attachments

  • Inspect message payload to find attachmentId values.
  • Retrieve contents with the attachments get operation using messageId and the attachment id.

Incremental sync with history

  • users.history.list requires a startHistoryId obtained from a message/thread historyId or a prior response. History IDs advance chronologically but are not contiguous; an out-of-date startHistoryId typically returns 404 — in that case a full sync is required (re-list messages/threads).
  • Limit and paging apply; when there is no nextPageToken, there are no more history records and the returned historyId can be stored for the next incremental request.

Settings, aliases, and identities

  • Send-as aliases: users.settings.sendAs.list → get sendAsEmail; manage alias settings with get/patch/update and remove with delete.
  • Verifying a send-as alias: users.settings.sendAs.verify triggers a verification flow that requires accepting a verification email—verification cannot be completed through the API alone without action on that verification message.
  • S/MIME: manage with users.settings.sendAs.smimeInfo.* operations; set the default S/MIME entry with setDefault.
  • Filters, forwarding addresses, delegates: list/create/delete/get via users.settings.filters.*, users.settings.forwardingAddresses.*, users.settings.delegates.*.
  • IMAP/POP/Auto-forwarding/Vacation/Language: get and set with the corresponding get and update operations under users.settings.*.
  • Client-side encryption (CSE): identities and keypairs are first-class resources. Keypair operations include create, list, enable, disable, and obliterateobliterate is irreversible.

Watch (push notifications)

  • Start a watch with users.watch; the response contains historyId and an expiration. Use users.stop to stop notifications. Watches require a valid push configuration in the request body (check the operation signature for required fields).

Non-obvious patterns and gotchas

  • The special userId value me is accepted everywhere and is the normal entry for the authenticated mailbox — you rarely need to pass an explicit address unless managing another account.
  • Many list endpoints are paginated. Each list response can include nextPageToken; request that token to fetch the next page. The list operations are the canonical way to discover resource IDs you will use elsewhere.
  • messages.list and threads.list return only IDs and minimal metadata. You must call messages.get or threads.get to retrieve the message payload, headers, parts, and attachment IDs.
  • Attachment retrieval requires two IDs: the messageId and the attachment id found in the message parts. You will not get the attachment body from messages.get without explicitly requesting it via the attachments endpoint.
  • format choices matter:
    • Use metadata + metadataHeaders when you only need a few headers to reduce payload size.
    • Use raw when you need the original MIME source.
    • Some operations or scopes (e.g., gmail.metadata) restrict the use of q or limit returned fields—check the operation signature for accepted parameters and scope implications.
  • history.list is fragile if the supplied startHistoryId is too old — the API will return 404. If you get 404, perform a full listing (e.g., messages.list) to re-synchronize and capture a fresh historyId.
  • Difference between deleting and trashing:
    • messages.trash and threads.trash move items to the Trash label and are reversible via untrash.
    • messages.delete and threads.delete permanently remove items.
  • Bulk operations exist for scale: users.messages.batchDelete and users.messages.batchModify accept lists of IDs for large changes. For per-message changes use messages.modify.
  • Send-as verification cannot be completed purely through the API; it usually requires interacting with a verification email sent to the alias.
  • CSE key operations include obliterate — treat it as permanent removal.
  • Watch responses include expiration; watches must be renewed. Use users.stop to cancel a watch.

Quick decision guide (pick the right operation)

  • Need mail IDs to operate on mail: call users.messages.list or users.threads.list.
  • Need full content/header/attachments for a specific item: call users.messages.get (or users.threads.get).
  • Want to send mail now: users.messages.send (or users.drafts.send for drafts).
  • Want to stage and edit before sending: users.drafts.create / users.drafts.update then users.drafts.send.
  • Change labels on one message: users.messages.modify. Change many messages: users.messages.batchModify.
  • Pull incremental mailbox changes: users.history.list with a valid startHistoryId; fall back to full listing on 404.
  • Manage aliases, filters, forwarding, or delegates: use the corresponding users.settings.* list/get/create/delete calls to discover and then act on the resource IDs.

Follow these patterns and you will reach the IDs and resource representations every other operation needs. When in doubt, list the resource that naturally contains the ID you require, then call the single-resource get/modify/delete operation for the action you need.