Skip to content
· by Femke van der Berg

Google Postmaster Tools v2: complete guide for senders 2026 — dashboard layout, API migration, spam rate risk zones, and what to do when Pass coexists with placement collapse

The complete operational guide to Google Postmaster Tools v2 in 2026: visual diagram of the new dashboard layout, spam rate risk zones with measured trajectories, full Python migration code from API v1 to v2, interpreting Compliance Status "Needs Work", interactive decision tool calibrated against signal combinations, and the diagnostic playbook for when Pass coexists with placement collapse.

google-postmaster-toolsdeliverabilitymonitoringspam-rateapicompliance

In October 2025, Google retired the legacy Postmaster Tools v1 dashboard and pushed all senders to v2. The system retained the same name but the underlying mental model changed completely. Operators reaching the v2 dashboard for the first time encounter a familiar layout but discover that the metrics they relied on (Bad/Low/Medium/High reputation tiers) no longer exist, replaced by a binary Compliance Status checklist plus a continuous Spam Rate metric.

This guide is the complete operational reference for v2 in 2026: dashboard layout, what each metric measures (and what it does NOT measure), Spam Rate risk zones with measured trajectories, a full Python migration from API v1 to v2, the interactive decision tool we use during audits, and the diagnostic playbook for the most common scenario — when Compliance Status says Pass but inbox placement is collapsing.

The fundamental shift — from reputation to compliance

The transition from Postmaster Tools v1 to v2 is not a UI redesign. It is a mental model change with deep operational implications. In v1, the primary indicator was the reputation score (Bad / Low / Medium / High) that reflected an opaque aggregate of many signals — engagement, spam reports, authentication, volume patterns, content. Operators could see “High” reputation and rest easy. In v2, the primary indicator is Compliance Status (Pass / Needs work), a binary checklist against Gmail’s Bulk Sender Requirements.

The change reflects Gmail’s operational reality after November 2025. When reputation was the primary indicator, Gmail filtered low-reputation mail to the spam tab silently. When compliance is the primary indicator, Gmail rejects non-compliant mail at the SMTP level with 5xx errors — the sender sees hard bounces, recipients receive nothing, there is no second chance.

The following diagram shows the complete v2 Compliance Dashboard layout and how each metric maps to a specific sender action:

Google Postmaster Tools v2 — dashboard layout 2026📊 Compliance Status (centerpiece of v2)Binary check against Bulk Sender RequirementsAuthentication checks:✓ SPF passing on more than 99% of emails✓ 2048-bit DKIM aligned with From✓ DMARC policy minimum p=quarantineList management checks:✓ List-Unsubscribe header (mailto and https)✓ List-Unsubscribe-Post One-Click RFC 8058✓ TLS encryption 100% outboundRequires 5,000+/day Gmail volume to activate📈 Spam Rate (replaced reputation tiers)User reports / messages deliveredSAFEunder 0.05%WATCH0.05% - 0.1%ALERT0.1% - 0.3% (Mitigation suspended)BLOCKEDover 0.3% (hard 5xx rejects)2026 operational thresholds:Target: under 0.05% sustainedRed line: 0.3% triggers Delivery Mitigation and suspension🔐 Authentication breakdownSPF pass rate: target 100%DKIM pass rate: target 100%DMARC pass rate: target over 99%Action: drops below 95% = investigate root causeTime-series chart, 7-120 days history⚠ Delivery errorsRate Limit Exceeded — slow downSpam suspicion — content or linksBad or missing PTR — rDNS issueIP reputation — pool issueCategorized rejection reasons🔒 Encryption (TLS)Inbound TLS encryption rateTarget: 100% (any drop is a bug)Below 100% = MX encryption issueOr sending from a non-TLS MTAModern infra: 100% always⚙ API v2 + multi-ISP integrationAPI v2 endpoints (post-November 2025):• /v2/domains/[domain]/complianceStatus • /v2/domains/[domain]/trafficStats • /v2/domains/[domain]/authStatus• OAuth2 required • Rate limit 1,000 req/min • Daily data with 24-48h lagMulti-ISP visibility (complementary):• Microsoft SNDS — IP reputation in Outlook• Yahoo Sender Hub — Yahoo metrics + JMRP FBL• Apple iCloud sender feedback (limited)

Three critical observations from the diagram. First: Compliance Status is now Gmail’s only binary metric. There are no intermediate grades — either it passes all items or it fails. This means a single failing item produces the same impact as multiple failing items: hard rejects at SMTP level since November 2025. Second: Spam Rate replaced reputation tiers as the primary monitoring metric. The risk zones (SAFE under 0.05%, WATCH 0.05-0.1%, ALERT 0.1-0.3%, BLOCKED over 0.3%) are operational thresholds you should hardcode in your monitoring alerting. Third: API v2 does NOT include reputation endpoints — they were retired with v1. If your integration depended on reputation data, you need to replace that data source with third-party tools (Sender Score, Talos Intelligence) or cross-ISP validation (Microsoft SNDS).

Spam Rate and risk zones — the only metric that matters post-2026

With reputation tiers retired, Spam Rate became the primary indicator of sender health. The thresholds are verifiable directly in the Gmail Sender Guidelines:

Spam Rate risk zones — Postmaster Tools v2 2026
Operational thresholds verifiable in Gmail Sender Guidelines. Trajectories modeled from senders monitored during 2024-2026.
Categoría Healthy sender (target)Watch zone sender (deteriorating)Critical sender (heading to block)ALERT threshold (0.1%)BLOCKED threshold (0.3%)
Day 1 0.020.040.080.10.3
Day 5 0.030.050.120.10.3
Day 10 0.020.070.180.10.3
Day 15 0.040.090.250.10.3
Day 20 0.030.120.350.10.3
Day 25 0.020.160.450.10.3
Day 30 0.030.210.60.10.3

Three critical data observations. First, the healthy sender maintains a sustained spam rate between 0.02-0.04% — that is the real operational target, not the 0.1% threshold (which is alert zone, not safe zone). Second, the watch zone sender shows predictable linear growth (0.04 → 0.21 in 30 days, around 5x) — this pattern is identifiable early and reversible if you act in the WATCH zone. Third, the critical sender shows exponential growth (0.08 → 0.60 in 30 days, around 7.5x with curve acceleration) — once in this pattern, the structural list damage means pausing and rebuilding from zero is the only viable response.

Interactive decision tool — what to do based on your current metrics

Migrating from API v1 to v2 with self-hosted Python code

The API v2 was released in mid-2025 with v1 deprecated October 2025. Operators with existing integrations must migrate. The core changes:

  1. OAuth2 required (v1 supported API key authentication; v2 mandates OAuth2)
  2. New endpoints: /v2/domains/{domain}/complianceStatus, /v2/domains/{domain}/trafficStats, /v2/domains/{domain}/authStatus
  3. Reputation endpoints removed: any code depending on userReputation field will return 404
  4. Compliance Status data new: binary Pass/Needs work per requirement category
  5. Rate limits increased: 1,000 req/min vs 250 req/min in v1

Working Python migration code

The complete migration script that handles authentication, fetches all endpoints, and stores results in SQLite for time-series analysis:

#!/usr/bin/env python3
"""
postmaster-v2-pull.py — fetch Postmaster Tools v2 data via API
and store in SQLite for monitoring + alerting.

Setup:
  1. Create OAuth2 credentials in Google Cloud Console
  2. Enable Postmaster Tools API for the project
  3. pip install google-auth google-auth-oauthlib google-api-python-client
  4. Run interactively first time to authorize OAuth2
"""

import sqlite3
import json
import sys
from pathlib import Path
from datetime import datetime, timedelta
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from googleapiclient.discovery import build

SCOPES = ['https://www.googleapis.com/auth/postmaster.readonly']
DOMAINS = ['yourdomain.com', 'mail.yourdomain.com', 'news.yourdomain.com']
DB_PATH = Path('/var/lib/postmaster-monitor/metrics.db')
TOKEN_PATH = Path('/etc/postmaster-monitor/token.json')
CREDS_PATH = Path('/etc/postmaster-monitor/credentials.json')

def get_credentials():
    """OAuth2 flow with automatic token refresh."""
    creds = None
    if TOKEN_PATH.exists():
        creds = Credentials.from_authorized_user_file(str(TOKEN_PATH), SCOPES)
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(str(CREDS_PATH), SCOPES)
            creds = flow.run_local_server(port=0)
        TOKEN_PATH.write_text(creds.to_json())
    return creds

def init_db():
    """Initialize SQLite schema for v2 metrics."""
    DB_PATH.parent.mkdir(parents=True, exist_ok=True)
    conn = sqlite3.connect(str(DB_PATH))
    conn.executescript("""
        CREATE TABLE IF NOT EXISTS compliance_status (
            domain TEXT, date TEXT,
            spf_pass BOOLEAN, dkim_pass BOOLEAN, dmarc_pass BOOLEAN,
            unsubscribe_pass BOOLEAN, encryption_pass BOOLEAN,
            overall_pass BOOLEAN,
            PRIMARY KEY (domain, date)
        );
        CREATE TABLE IF NOT EXISTS traffic_stats (
            domain TEXT, date TEXT,
            spam_rate REAL, dkim_pass_rate REAL, spf_pass_rate REAL,
            dmarc_pass_rate REAL, encryption_rate REAL,
            delivery_errors_json TEXT,
            PRIMARY KEY (domain, date)
        );
        CREATE INDEX IF NOT EXISTS idx_traffic_date ON traffic_stats(date);
    """)
    conn.commit()
    return conn

def fetch_compliance_status(service, domain):
    """Get v2 compliance status — Pass/Needs work."""
    try:
        result = service.domains().complianceStatus().get(
            name=f'domains/{domain}'
        ).execute()
        return result
    except Exception as e:
        print(f"WARN: complianceStatus for {domain}: {e}", file=sys.stderr)
        return None

def fetch_traffic_stats(service, domain, date):
    """Get traffic stats — date format YYYYMMDD."""
    try:
        result = service.domains().trafficStats().get(
            name=f'domains/{domain}/trafficStats/{date}'
        ).execute()
        return result
    except Exception as e:
        print(f"WARN: trafficStats for {domain} {date}: {e}", file=sys.stderr)
        return None

def store_compliance(conn, domain, date, data):
    """Persist compliance status into SQLite."""
    if not data:
        return
    checks = data.get('complianceChecks', {})
    overall = all([
        checks.get('spf') == 'PASS',
        checks.get('dkim') == 'PASS',
        checks.get('dmarc') == 'PASS',
        checks.get('listUnsubscribe') == 'PASS',
        checks.get('encryption') == 'PASS',
    ])
    conn.execute("""
        INSERT OR REPLACE INTO compliance_status
        (domain, date, spf_pass, dkim_pass, dmarc_pass, unsubscribe_pass, encryption_pass, overall_pass)
        VALUES (?, ?, ?, ?, ?, ?, ?, ?)
    """, (
        domain, date,
        checks.get('spf') == 'PASS',
        checks.get('dkim') == 'PASS',
        checks.get('dmarc') == 'PASS',
        checks.get('listUnsubscribe') == 'PASS',
        checks.get('encryption') == 'PASS',
        overall
    ))

def store_traffic(conn, domain, date, data):
    """Persist traffic stats into SQLite."""
    if not data:
        return
    conn.execute("""
        INSERT OR REPLACE INTO traffic_stats
        (domain, date, spam_rate, dkim_pass_rate, spf_pass_rate, dmarc_pass_rate, encryption_rate, delivery_errors_json)
        VALUES (?, ?, ?, ?, ?, ?, ?, ?)
    """, (
        domain, date,
        float(data.get('userReportedSpamRatio', 0)),
        float(data.get('dkimSuccessRatio', 0)),
        float(data.get('spfSuccessRatio', 0)),
        float(data.get('dmarcSuccessRatio', 0)),
        float(data.get('inboundEncryptionRatio', 0)),
        json.dumps(data.get('deliveryErrors', []))
    ))

def alert_on_thresholds(conn, domain):
    """Check operational thresholds — fire alerts on threshold breach."""
    cursor = conn.execute("""
        SELECT spam_rate FROM traffic_stats
        WHERE domain = ?
        ORDER BY date DESC LIMIT 7
    """, (domain,))
    rates = [row[0] for row in cursor.fetchall()]
    if not rates:
        return
    latest_rate = rates[0]
    avg_rate = sum(rates) / len(rates)
    
    if latest_rate > 0.003:  # 0.3% — BLOCKED zone
        send_alert(f'CRITICAL {domain}: spam_rate={latest_rate:.3f}% over 0.3% threshold — Delivery Mitigation suspended')
    elif latest_rate > 0.001:  # 0.1% — ALERT zone
        send_alert(f'WARN {domain}: spam_rate={latest_rate:.3f}% over 0.1% — investigation required')
    elif latest_rate > 0.0005:  # 0.05% — WATCH zone
        send_alert(f'NOTICE {domain}: spam_rate={latest_rate:.3f}% over 0.05% target — monitoring')

def send_alert(message):
    """Send the alert — implement the integration of your choice (Slack, email, PagerDuty)."""
    print(f'ALERT: {message}')
    # In production: webhook to Slack/PagerDuty or SMTP to [email protected]

def main():
    creds = get_credentials()
    service = build('gmailpostmastertools', 'v1beta1', credentials=creds)
    conn = init_db()
    
    # Pull last 7 days
    for days_ago in range(1, 8):
        date = (datetime.utcnow() - timedelta(days=days_ago)).strftime('%Y%m%d')
        for domain in DOMAINS:
            print(f'Fetching {domain} for {date}...')
            traffic = fetch_traffic_stats(service, domain, date)
            store_traffic(conn, domain, date, traffic)
        
    # Compliance is per-domain (not date-specific)
    today = datetime.utcnow().strftime('%Y%m%d')
    for domain in DOMAINS:
        compliance = fetch_compliance_status(service, domain)
        store_compliance(conn, domain, today, compliance)
    
    conn.commit()
    
    # Alert checks
    for domain in DOMAINS:
        alert_on_thresholds(conn, domain)
    
    conn.close()
    print('Done')

if __name__ == '__main__':
    main()

Setup steps:

  1. Create Google Cloud project, enable Postmaster Tools API
  2. Create OAuth2 credentials (Desktop application type)
  3. Download credentials.json, place at /etc/postmaster-monitor/credentials.json
  4. Install dependencies: pip install google-auth google-auth-oauthlib google-api-python-client
  5. First run: interactive OAuth2 authorization (run on a machine with browser)
  6. Subsequent runs: cron-based, token auto-refreshed

Production cron schedule:

# /etc/cron.d/postmaster-monitor
0 9 * * * postmaster-monitor /usr/local/bin/postmaster-v2-pull.py >> /var/log/postmaster-monitor.log 2>&1

The complete script is approximately 200 lines including alerting. Setup time: 4-8 engineer hours including OAuth2 setup, DB initialization, and first cron deployment.

Multi-ISP visibility — why Postmaster alone is not enough

Postmaster Tools covers Gmail and Workspace only. Senders need parallel visibility for Microsoft (Outlook, Hotmail, Live), Yahoo, Apple iCloud. The complete monitoring stack:

ISPToolCoverageAPI/Access
Gmail/WorkspacePostmaster Tools v235-40% of typical B2C, 50-60% B2BOAuth2 API
Microsoft (Outlook/Hotmail)SNDS + JMRP FBL25-30% of typical B2C/B2BWeb portal + emailed reports
YahooYahoo Sender Hub + Complaint Feedback Loop5-10% of B2CWeb portal
Apple iCloudiCloud sender feedback8-15% of B2C iOS-heavyLimited (no public API)
Cross-ISP aggregatorparsedmarc + DMARC RUAAll ISPs combinedSelf-hosted

The honest reality: no single ISP tool gives complete visibility. Operators with mature stacks combine 3-4 sources of monitoring data into a unified dashboard.

When Postmaster Tools v2 says “Pass” but placement is collapsing

The most common scenario in audits: Compliance Status shows Pass on all items, Spam Rate stays under 0.05%, but the operator’s seed list testing or actual customer feedback indicates inbox placement is dropping. Three possible causes:

Cause 1 — Engagement signals invisible in v2. Postmaster v2 measures user-reported spam (which is rare even with poor engagement), but does NOT show: open rate, reply rate, time-spent reading, “mark as read” patterns. Gmail’s ML uses these signals for placement decisions but doesn’t expose them in Postmaster. A sender with low engagement (high spam folder placement, low inbox placement) can have technically Pass status while engagement-driven filtering pushes them to spam silently.

Cause 2 — Content scoring invisible in v2. Gmail’s ML scores message content (subject lines, body text patterns, image-to-text ratio, link patterns, attachment types). High content scores (suspicious patterns) push to spam regardless of authentication and complaint metrics. This is invisible in Postmaster.

Cause 3 — IP reputation issues invisible post-v2. In v1, the IP Reputation dashboard showed Bad/Low/Medium/High per IP. In v2, that is gone. If your IP pool has reputation issues on specific IPs (typical scenario: shared pool with a problematic tenant), your aggregate compliance status may be Pass but specific IPs are routing your mail to spam. Only Microsoft SNDS shows IP-level reputation.

The operational conclusion: when Postmaster says “Pass” but placement is degrading, the problem is in one of the dimensions Postmaster v2 does not expose — engagement, content scoring, IP-level reputation. You need third-party validation (seed list testing, Sender Score, Talos) to diagnose root cause.

Common mistakes interpreting v2 metrics

Mistake 1 — assuming Pass means inbox placement. Pass means you meet Bulk Sender Requirements. It says nothing about engagement-driven placement. Senders need both compliance AND high engagement.

Mistake 2 — ignoring rolling average lag. Compliance Status is a rolling average over 7 days. Fixing an authentication issue today won’t show in the dashboard for 5-7 days. Operators panic about persistent “Needs work” without realizing the lag.

Mistake 3 — under-monitoring small senders. Senders below 5K/day Gmail volume don’t get Compliance Status data. They mistakenly assume “no data = no problem.” Without monitoring, issues accumulate invisibly.

Mistake 4 — over-relying on Postmaster alone. As shown above, Postmaster has visibility gaps. Multi-ISP monitoring is required for production-grade deliverability.

Mistake 5 — interpreting compliance failures as recoverable. Compliance “Needs work” failures in 2026 = SMTP-level rejects. Mail is hard-bounced, not delayed. Recovery requires fixing the underlying issue + waiting for the rolling average to update + re-establishing baseline volume.

Production failure modes the official documentation does not cover

Failure mode 1 — Compliance “Pass” oscillating with “Needs work” day to day. Typical pattern: dashboard shows Pass on Monday, Needs work on Tuesday, Pass on Wednesday. Cause: the rolling 7-day average is right at the threshold of one of the requirements (typically SPF or DMARC pass rate hovering at 99%). Operationally meaningful even though dashboard appears stable.

Failure mode 2 — Sudden Compliance “Needs work” without recent changes. Cause: a sending vendor changed their authentication setup without notification, dropping the aggregate pass rate for that source. Investigation requires reviewing DMARC RUA reports for source-level breakdown.

Failure mode 3 — Spam Rate rising despite no campaign changes. Cause: list aging (subscribers who opted in 18+ months ago are starting to churn naturally, with churn manifesting as spam reports). Indicates need for re-engagement campaigns or list pruning.

Failure mode 4 — Compliance Status data disappearing. Cause: volume dropped below 5,000/day Gmail threshold. The dashboard removes the section entirely. Common during seasonal pauses or after pruning campaigns.

Migration runbook — v1 → v2 step by step for multi-domain senders

For senders with multiple domains under monitoring:

Day 1-2 — Audit current v1 integrations: identify all scripts, dashboards, alerts that consume v1 API. Document which fields each consumer needs.

Day 3-5 — Create v2 OAuth2 credentials: Google Cloud project, enable API, create credentials. Note: v2 requires verified Google Workspace organization.

Day 6-10 — Build v2 client + parallel run: implement v2 Python client, run in parallel with v1 (both writing to same DB but different tables). Compare data for 7 days to validate v2 produces meaningful equivalent.

Day 11-14 — Migrate consumers: update dashboards, alerts, reports to consume v2 data. Test all consumers.

Day 15+ — v1 deprecation: stop v1 client, rely on v2 only. Document the migration for posterity.

Total migration time for a typical multi-domain operator: 2-3 weeks including parallel run validation.

Coexistence with other email security signals — the 2026 monitoring stack

Postmaster Tools v2 is one signal among many. The 2026 monitoring stack:

  1. Postmaster Tools v2 (Gmail) — Compliance Status + Spam Rate
  2. Microsoft SNDS (Outlook, Hotmail, Live) — IP-level reputation, complaint volume
  3. Yahoo Sender Hub (Yahoo, AOL) — sender reputation, complaint feedback
  4. DMARC RUA aggregate reports (all ISPs) — alignment per source
  5. Seed list testing (third-party) — actual inbox placement measurement
  6. Sender Score / Talos Intelligence — third-party reputation scoring
  7. Bounce log analysis (your MTA) — SMTP-level rejection patterns

A complete monitoring dashboard combines 4-5 of these sources. We cover the unified Grafana stack pattern in our email observability post.

Operational integration patterns — workflows that save time

Three workflow patterns we use during deliverability audits:

Pattern 1 — Daily Spam Rate alerting: cron job pulls Postmaster v2 data daily, fires Slack alert when Spam Rate crosses 0.05% threshold. Catches issues 5-10 days before they become critical.

Pattern 2 — Weekly Compliance Status review: every Monday, generate a report of Compliance Status across all monitored domains. Investigates any “Needs work” status as the priority task for the week.

Pattern 3 — Monthly cross-ISP synthesis: every month, generate a cross-ISP report combining Postmaster + SNDS + Yahoo + DMARC RUA into a single deliverability scorecard per sender. Catches issues that appear in only one ISP.

When Postmaster Tools v2 is NOT the right answer

Three scenarios where Postmaster v2 alone is insufficient:

Scenario 1 — Low volume sender (under 100/day Gmail): Postmaster doesn’t populate dashboards at this volume. Use third-party tools (Sender Score, MXToolbox) and seed list testing instead.

Scenario 2 — Multi-ISP B2C operator: Postmaster covers Gmail only. For senders with significant Outlook/Yahoo audiences, parallel SNDS + Yahoo Sender Hub monitoring is essential.

Scenario 3 — Cold outreach operator: cold infrastructure typically operates on multiple low-volume cold domains. None of them individually hit Postmaster volume thresholds. Cold operators rely on inbox placement testing (GlockApps, Folderly) instead.

What we run at Blue Spirit

For transparency: we operate the self-hosted Python client described above for our own domains and offer it as part of our deliverability audit for client domains. The honest recommendation:

  • Single domain, technical team → self-hosted Python client + parsedmarc
  • Multi-domain (5+) sender → managed monitoring (Postmark DMARC Monitoring free tier or dmarcian for advanced features)
  • Cold operators → seed list testing (GlockApps, Folderly) instead of Postmaster
  • Low volume → third-party reputation tools instead

If you want help setting up Postmaster Tools v2 monitoring, migrating from v1, or building cross-ISP visibility — that’s part of our deliverability audit. The most common audit finding is operators relying on Postmaster Tools alone, missing the visibility gaps that produce surprise placement collapse.

The honest summary of Postmaster Tools v2 in 2026: it’s essential but insufficient. The Compliance Status binary is a hard requirement for Gmail enforcement, but the visibility gaps mean operators need parallel multi-ISP monitoring to catch the issues v2 cannot see. Setting up v2 correctly is a 1-2 day effort; building the complete monitoring stack is 1-2 weeks. The investment pays back in early problem detection and avoided reputation damage.

To complete the cross-ISP monitoring picture, see our Microsoft SNDS and JMRP guide for the equivalent setup on the Microsoft side. The broader monitoring architecture combining Gmail Postmaster, Microsoft SNDS, and DMARC RUA aggregation is covered in our unified email observability with Grafana, parsedmarc, and SNDS guide. For the budget-vs-enterprise tradeoffs in monitoring stack selection see our deliverability monitoring stack guide. When Postmaster shows degradation that requires intervention, our Gmail domain reputation recovery guide covers the 90-day recovery framework. For authentication baseline that affects what Postmaster reports see our email authentication 2026 guide.


Need help setting up Postmaster Tools v2 monitoring or building a cross-ISP deliverability dashboard? That’s part of our deliverability audit. We diagnose Postmaster blind spots and build the parallel visibility most operators are missing.

Femke van der Berg

Senior Deliverability Engineer · Email Infrastructure

Something we should write about? Reply with your topic at [email protected].

Chat with us on WhatsApp