List and search quarantined messages

This page explains how to find the messages that are held in your Google Workspace admin quarantines using the Mail Admin Quarantine API.

The API offers two methods on the customers.quarantinedMessages resource:

  • The list method returns quarantined messages without any filtering. Use it to page through everything in your quarantines.
  • The search method narrows the results with a structured filter, a Gmail search query, or both. Use it for triage workflows, such as retrieving only inbound messages that are pending review.

Both methods return messages from the last 30 days, and both return the same basic metadata for each message. To retrieve headers, body, attachments, or the raw message, see Get message details.

Prerequisites

  • You completed the steps in Set up the API.
  • An access token that impersonates an administrator with an admin quarantine privilege and includes the https://www.googleapis.com/auth/gmail.admin.quarantine or https://www.googleapis.com/auth/gmail.admin.quarantine.readonly scope. See Authorize with domain-wide delegation.

List quarantined messages

To list quarantined messages, send a GET request to the list method on the customers.quarantinedMessages resource of your customer:

GET https://mailadminquarantine.googleapis.com/v1/customers/CUSTOMER_ID/quarantinedMessages?pageSize=50
Authorization: Bearer ACCESS_TOKEN

Replace CUSTOMER_ID with your customer ID.

The list method accepts the following query parameters:

Parameter Description
pageSize The maximum number of messages to return per page, from 1 to 300. Always set this parameter explicitly.
pageToken The nextPageToken value from a previous response. Use it to retrieve the next page.

To search quarantined messages, send a POST request to the :search custom method on the customers.quarantinedMessages resource with a JSON body:

POST https://mailadminquarantine.googleapis.com/v1/customers/CUSTOMER_ID/quarantinedMessages:search
Authorization: Bearer ACCESS_TOKEN
Content-Type: application/json

{
  "filter": "status = PENDING_TRIAGE AND direction = INBOUND",
  "query": "from:suspicious@example.com",
  "pageSize": 50
}

The request body accepts the following fields. All fields are optional:

Field Description
filter A structured filter in AIP-160 syntax. See Filter syntax.
query A Gmail search query, such as has:attachment or from:suspicious@example.com. The query uses the same operators as the Gmail search box. See Search operators you can use with Gmail.
pageSize The maximum number of messages to return per page, from 1 to 300. Always set this field explicitly.
pageToken The nextPageToken value from a previous response.

When you set both filter and query, the API returns only messages that match both.

Filter syntax

The filter field supports the following fields. Combine them with the AND operator. Other operators, such as OR and NOT, aren't supported.

Field Supported comparisons Values
status = PENDING_TRIAGE, RELEASED, or DENIED.
direction =, != INBOUND or OUTBOUND.
quarantine_name (or quarantineName) = The display name of a quarantine as shown in the Google Admin console, for example "Default".

The following examples show valid filters:

status = PENDING_TRIAGE
status = PENDING_TRIAGE AND direction = INBOUND
direction != OUTBOUND AND quarantine_name = "Default"

An invalid filter returns a 400 INVALID_ARGUMENT error.

Response

Both methods return a list of QuarantinedMessage resources with basic metadata, plus a nextPageToken if more results are available:

{
  "quarantinedMessages": [
    {
      "name": "customers/01abc23de/quarantinedMessages/user@example.com:18d3ef45a8b2c1d0",
      "messageId": "18d3ef45a8b2c1d0",
      "messageOwner": "user@example.com",
      "quarantines": [
        "customers/01abc23de/quarantines/0"
      ],
      "receiveTime": "2026-09-22T10:15:30Z",
      "direction": "INBOUND",
      "state": "PENDING_TRIAGE",
      "retentionExpireTime": "2026-10-22T10:15:30Z",
      "triggeredRules": [
        {
          "policyId": "123",
          "ruleId": "456",
          "displayName": "Inbound phishing protection"
        }
      ]
    }
  ],
  "nextPageToken": "CAESBAgBEA..."
}
Field Description
name The resource name of the message. Use it in subsequent get, release, and deny calls on the customers.quarantinedMessages resource.
messageId The immutable Gmail message ID.
messageOwner The email address of the mailbox that owns the message.
quarantines The resource names of the quarantines that hold the message. Call the get method of the customers.quarantines resource to get a quarantine's display name.
receiveTime When Gmail received the message.
direction INBOUND if a user received the message, or OUTBOUND if a user sent it.
state PENDING_TRIAGE, RELEASED, or DENIED.
retentionExpireTime When the quarantine stops retaining the message.
triggeredRules The rules that caused the message to be quarantined.
unreachable Accounts for which the service couldn't retrieve quarantined messages. If present, retry the request later.

Page through results

To retrieve all matching messages:

  1. Send the first request with a pageSize.
  2. If the response contains a nextPageToken, repeat the request with the same parameters and set pageToken to that value.
  3. Stop when the response doesn't contain a nextPageToken.

The following Python example pages through all inbound messages that are pending triage:

import requests

BASE_URL = 'https://mailadminquarantine.googleapis.com/v1'
CUSTOMER_ID = '01abc23de'  # Your customer ID without the leading 'C'.
headers = {
    'Authorization': f'Bearer {access_token}',
    'Content-Type': 'application/json',
}

search_url = f'{BASE_URL}/customers/{CUSTOMER_ID}/quarantinedMessages:search'
body = {
    'filter': 'status = PENDING_TRIAGE AND direction = INBOUND',
    'pageSize': 100,
}
messages = []
while True:
  response = requests.post(search_url, headers=headers, json=body)
  response.raise_for_status()
  result = response.json()
  messages.extend(result.get('quarantinedMessages', []))
  page_token = result.get('nextPageToken')
  if not page_token:
    break
  body['pageToken'] = page_token

print(f'Found {len(messages)} messages pending triage.')

Next steps