{
  "openapi": "3.1.0",
  "info": {
    "title": "EmailScore API",
    "version": "2.0.0",
    "description": "Email validation, risk scoring, identity signals, and bounce diagnostics.\n\n## Overview\nEmailScore helps teams decide which email addresses to accept, which contacts need further verification, and how to respond when delivery fails.\n\n## Workflows and limits\n- **Screen signups**: Review disposable-address, domain, and suspicious-pattern signals.\n- **Score domains**: Check a domain on its own (registration age, mail DNS, disposable providers) with `POST /v1/domain`, or up to 10,000 at once with `POST /v1/domain/bulk`.\n- **Evaluate contact lists**: Screen batches and identify contacts needing further verification.\n- **Recognize email aliases**: Use normalization and fingerprints in your own identity workflows.\n- **Diagnose delivery failures**: Classify supplied mailserver errors and review recommended next actions.\n\nRisk scores and decision recommendations do not prove mailbox ownership, human identity, or successful delivery. Server-side evaluation timing is distinct from end-to-end API latency. Diagnostic processing can involve an external service when configured; do not assume offline processing or zero retention.\n\n## Authentication\nPass your secret API key in the standard HTTP `Authorization` header using the `Bearer` scheme on all requests:\n\n```http\nAuthorization: Bearer es_live_your_32_character_api_key\n```\n\n> API keys can be managed from your EmailScore developer console. Never expose production secret keys in client-side code or public repositories.\n\n## Quickstart by Language\n\n### cURL\nCheck a single email directly from your terminal:\n```bash\ncurl -sS -X POST \"https://api.emailscore.io/v1/email\" \\\n  -H \"Authorization: Bearer YOUR_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"email\": \"sarah.jenkins@gmail.com\"}'\n```\n\nClean an entire batch with gzip compression:\n```bash\ncurl -sS -X POST \"https://api.emailscore.io/v1/email/bulk\" \\\n  -H \"Authorization: Bearer YOUR_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Accept-Encoding: gzip\" \\\n  -d '{\"emails\": [\"sarah.jenkins@gmail.com\", \"alex@stripe.com\", \"bot@10minutemail.com\"]}'\n```\n\nScore a domain on its own:\n```bash\ncurl -sS -X POST \"https://api.emailscore.io/v1/domain\" \\\n  -H \"Authorization: Bearer YOUR_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"domain\": \"acme.com\"}'\n```\n\nTriage an incoming bounce diagnostic string:\n```bash\ncurl -sS -X POST \"https://api.emailscore.io/v1/bounce/diagnose\" \\\n  -H \"Authorization: Bearer YOUR_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"diagnostic\": \"550 5.1.1 <user@example.com>: Recipient address rejected: User unknown\"}'\n```\n\n### Ruby\nIdiomatic Ruby using standard library `Net::HTTP` and `JSON`:\n```ruby\nrequire 'net/http'\nrequire 'uri'\nrequire 'json'\n\nuri = URI('https://api.emailscore.io/v1/email')\nhttp = Net::HTTP.new(uri.host, uri.port)\nhttp.use_ssl = true\n\nreq = Net::HTTP::Post.new(uri.path, {\n  'Authorization' => \"Bearer #{ENV['EMAILSCORE_API_KEY']}\",\n  'Content-Type' => 'application/json'\n})\nreq.body = { email: 'sarah.jenkins@gmail.com' }.to_json\n\nresponse = http.request(req)\ntriage = JSON.parse(response.body)\n\nputs \"Score: #{triage['score']}/100 | Decision: #{triage['decision'].upcase}\"\nputs \"Fingerprint: #{triage.dig('identity', 'fingerprint')}\"\nputs \"Recommendation: #{triage['recommendation']}\"\n\nif triage['decision'] == 'deny'\n  # Block disposable or fraudulent signup\n  raise \"Email rejected: #{triage['recommendation']}\"\nend\n```\n\n### Python\nUsing `requests` with timeout and exception safety:\n```python\nimport os, requests\n\nAPI_KEY = os.environ[\"EMAILSCORE_API_KEY\"]\n\ndef verify_email(email: str) -> dict:\n    res = requests.post(\n        \"https://api.emailscore.io/v1/email?format=compact\",\n        headers={\"Authorization\": f\"Bearer {API_KEY}\"},\n        json={\"email\": email},\n        timeout=1.0,\n    )\n    res.raise_for_status()\n    return res.json()\n\nresult = verify_email(\"sarah.jenkins@gmail.com\")\nprint(f\"Decision: {result['decision'].upper()} (Score: {result['score']}/100)\")\nif result[\"decision\"] == \"deny\":\n    print(\"Rejected:\", result[\"recommendation\"])\n```\n\n### Node.js / TypeScript\nUsing native `fetch` (compatible with Node 18+, Next.js Edge, and Cloudflare Workers):\n```typescript\nconst response = await fetch('https://api.emailscore.io/v1/email?format=compact', {\n  method: 'POST',\n  headers: {\n    'Authorization': `Bearer ${process.env.EMAILSCORE_API_KEY}`,\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({ email: 'sarah.jenkins@gmail.com' }),\n});\n\nconst triage = await response.json();\nif (triage.decision === 'deny') {\n  throw new Error(triage.did_you_mean ? `Did you mean ${triage.did_you_mean}?` : triage.recommendation);\n}\n\nconsole.log(`Verified ${triage.email} -> Score ${triage.score} (${triage.decision})`);\n```\n\n### Go\nUsing standard `net/http` with zero third-party dependencies:\n```go\npackage main\n\nimport (\n    \"bytes\"\n    \"encoding/json\"\n    \"fmt\"\n    \"io\"\n    \"net/http\"\n    \"os\"\n)\n\nfunc main() {\n    payload := []byte(`{\"email\": \"sarah.jenkins@gmail.com\"}`)\n    req, err := http.NewRequest(\"POST\", \"https://api.emailscore.io/v1/email\", bytes.NewBuffer(payload))\n    if err != nil {\n        panic(err)\n    }\n\n    req.Header.Set(\"Authorization\", \"Bearer \"+os.Getenv(\"EMAILSCORE_API_KEY\"))\n    req.Header.Set(\"Content-Type\", \"application/json\")\n\n    client := &http.Client{}\n    resp, err := client.Do(req)\n    if err != nil {\n        panic(err)\n    }\n    defer resp.Body.Close()\n\n    body, _ := io.ReadAll(resp.Body)\n    var result map[string]any\n    json.Unmarshal(body, &result)\n\n    fmt.Printf(\"Score: %v | Decision: %v\\n\", result[\"score\"], result[\"decision\"])\n}\n```\n\n### PHP\nModern PHP 8+ cURL implementation:\n```php\n<?php\n$apiKey = getenv('EMAILSCORE_API_KEY');\n$ch = curl_init(\"https://api.emailscore.io/v1/email\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_POST, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"Authorization: Bearer {$apiKey}\",\n    'Content-Type: application/json'\n]);\ncurl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(['email' => 'sarah.jenkins@gmail.com']));\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\n$result = json_decode($response, true);\necho \"Score: \" . $result['score'] . \"/100 | Decision: \" . strtoupper($result['decision']) . \"\\n\";\necho \"Fingerprint: \" . $result['identity']['fingerprint'] . \"\\n\";\n```\n\n### Rust\nAsync verification with `reqwest` and `tokio`:\n```rust\nuse reqwest::header::{AUTHORIZATION, CONTENT_TYPE};\nuse serde_json::{json, Value};\n\n#[tokio::main]\nasync fn main() -> Result<(), Box<dyn std::error::Error>> {\n    let api_key = std::env::var(\"EMAILSCORE_API_KEY\")?;\n    let client = reqwest::Client::new();\n    let res = client\n        .post(\"https://api.emailscore.io/v1/email\")\n        .header(AUTHORIZATION, format!(\"Bearer {}\", api_key))\n        .header(CONTENT_TYPE, \"application/json\")\n        .json(&json!({ \"email\": \"sarah.jenkins@gmail.com\" }))\n        .send()\n        .await?;\n\n    let data: Value = res.json().await?;\n    println!(\"Score: {} | Decision: {}\", data[\"score\"], data[\"decision\"]);\n    println!(\"Fingerprint: {}\", data[\"identity\"][\"fingerprint\"]);\n    Ok(())\n}\n```\n\n## Response Formats\nChoose a response representation based on the information your application needs:\n\n1. **Full Format (Default)**: Returns detailed signals, domain information, mailbox classifications, and identity fingerprints.\n2. **Compact Format (`?format=compact`)**: Flattened decision payload. Returns `score`, `decision`, `risk_level`, `account_type`, `is_business_email`, `is_disposable`, `did_you_mean`, `fingerprint`, and `evaluation_time_ms`. Ideal for edge firewalls, mobile apps, and high-volume signup forms.\n3. **Custom Sparse Projections (`?fields=...`)**: Query exact dotted attributes (e.g. `?fields=score,decision,identity.fingerprint`).\n\n## Wire Compression\nEmailScore natively supports modern stream compression algorithms on both inbound batches and outbound responses:\n- **Outbound Responses**: Supply standard `Accept-Encoding: gzip, br, zstd, deflate` headers. The edge gateway negotiates `zstd`, `br` (maximum density), or `gzip`.\n- **Inbound Batch Uploads**: When submitting up to 10,000 emails to `POST /v1/email/bulk`, compress your JSON body and send `Content-Encoding: gzip`.\n\n## Decision & Risk Matrix\nEmailScore maps signals to risk recommendations. Apply these recommendations according to your policy; they are not proof of delivery or identity:\n\n| Decision | Score Range | Risk Level | Threat Profile & Criteria | Recommended Action |\n| :--- | :--- | :--- | :--- | :--- |\n| **`allow`** | 70 – 100 | `low` | Lower-risk combination of address, domain, and identity signals. | Consider accepting under your policy; use ownership verification where required. |\n| **`challenge`** | 40 – 69 | `medium` | Ambiguous identity patterns, newly registered domains (<90 days), role-based mailboxes (admin/support), minor typos. | Soft check: prompt user for email OTP confirmation or CAPTCHA. |\n| **`deny`** | 1 – 39 | `high` | High-risk address or identity patterns. | Review supporting signals and apply your rejection or review policy. |\n| **`deny`** | 0 | `critical` | Critical address or domain indicators, such as invalid syntax or a disposable domain. | Review the reason and apply your policy; the score is not a bounce guarantee. |\n\n## Post-Flight SMTP Bounce Diagnostics\nWhen receiving bounces from ESP webhooks (SendGrid, Postmark, AWS SES, Mailgun), submit cryptic RFC error strings to `POST /v1/bounce/diagnose` (metered at **5 credits** per triage):\n- **`prune_permanent`**: Mailbox does not exist (550 5.1.1), domain is dead, or recipient rejected permanently. **Action**: Suppress future sends to the recipient according to your delivery policy.\n- **`retry_transient`**: Temporary failure (451 4.4.1 mailbox full, greylisting, ISP connection throttle). **Action**: Queue retry with exponential backoff.\n\n## Rate Limits & Telemetry Headers\nProduction edge clusters enforce rate limits according to your tier. All responses include real-time quota telemetry headers:\n\n| Header | Description |\n| :--- | :--- |\n| `X-RateLimit-Limit` | Maximum allowable requests in current time window. |\n| `X-RateLimit-Remaining` | Remaining requests before HTTP 429 throttle. |\n| `X-RateLimit-Reset` | Unix epoch timestamp when rate limit counter resets. |\n\nIf rate limits or credit quotas are exceeded, the API returns `429 Too Many Requests` with a structured JSON error body.\n\n## Standard HTTP Status & Error Codes\n\n| Status Code | Reason | Resolution |\n| :--- | :--- | :--- |\n| **`200 OK`** | Successful evaluation. | Check `decision` (`allow`, `challenge`, `deny`). |\n| **`400 Bad Request`** | Missing `email` or `domain`, an empty array, or more than 10,000 items in one batch. | Ensure request payload is valid JSON and contains required fields; split batches into chunks of <=10,000 items. |\n| **`401 Unauthorized`** | Missing or invalid API key. | Supply valid `Authorization: Bearer es_live_...` header. |\n| **`404 Not Found`** | Endpoint does not exist. | Verify target URI path and method. |\n| **`413 Payload Too Large`** | Request body larger than 2 MB. | Send smaller batches. |\n| **`429 Too Many Requests`** | Rate limit or credit quota exhausted. | Back off exponentially or top up PAYG credits in developer console. |\n| **`500 Internal Server Error`** | Edge gateway execution fault. | Retry request with exponential jitter. |\n| **`503 Service Unavailable`** | DNS resolver cluster synchronization. | Temporary failover; retry after 1-2 seconds. |\n\n## Data Handling & Acceptable Use\n- **Data handling**: Do not infer logging, retention, or compliance commitments from the scoring architecture. Diagnostic processing can use an external service when configured; review the published privacy policy before submitting personal data.\n- **Anti-Harvesting**: EmailScore strictly forbids directory harvest attacks (DHA), brute-force dictionary probing, or unauthorized scraping. All queries must originate from genuine user signup flows or direct opt-in customer lists.",
    "contact": {
      "name": "EmailScore Developer Support",
      "url": "https://emailscore.io",
      "email": "support@emailscore.io"
    }
  },
  "servers": [
    {
      "url": "https://api.emailscore.io",
      "description": "Production Edge Gateway"
    },
    {
      "url": "http://localhost:8080",
      "description": "Local Development Server"
    }
  ],
  "tags": [
    {
      "name": "Core Verification",
      "description": "Sub-millisecond single-email, bulk, and domain risk evaluation"
    },
    {
      "name": "Post-Flight Diagnostics",
      "description": "Raw SMTP bounce triage and suppression list classification"
    },
    {
      "name": "Engine Telemetry",
      "description": "Cluster health, capacity, and feature introspection"
    }
  ],
  "components": {
    "securitySchemes": {
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "API Key (es_live_...)",
        "description": "Secret API key obtained from your dashboard."
      }
    },
    "schemas": {
      "ErrorResponse": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "Standardized error message or machine-readable reason code."
          },
          "message": {
            "type": "string",
            "description": "Optional extended error explanation or remediation steps."
          }
        },
        "example": {
          "error": "Invalid or revoked API key"
        }
      },
      "CheckSingleRequest": {
        "type": "object",
        "properties": {
          "email": {
            "type": "string",
            "required": true,
            "example": "sarah.jenkins@gmail.com",
            "description": "The raw email address to score."
          },
          "format": {
            "type": "string",
            "required": false,
            "example": "full",
            "description": "Optional format override in request body (`full` or `compact`)."
          },
          "fields": {
            "type": "string",
            "required": false,
            "example": "score,decision,identity.normalized_email",
            "description": "Optional sparse field projection override in request body."
          }
        }
      },
      "CheckSingleResponse": {
        "type": "object",
        "properties": {
          "email": {
            "type": "string",
            "description": "Original email address evaluated."
          },
          "local_part": {
            "type": "string",
            "description": "Extracted local part (username) before the @ symbol."
          },
          "domain": {
            "type": "string",
            "description": "Extracted domain name after the @ symbol."
          },
          "score": {
            "type": "integer",
            "description": "Deterministic quality score from 0 (fraudulent/dead) to 100 (high confidence legitimate)."
          },
          "decision": {
            "type": "string",
            "enum": [
              "allow",
              "challenge",
              "deny"
            ],
            "description": "Risk-based policy recommendation: `allow`, `challenge`, or `deny`. Review supporting signals; this is not proof of ownership, human identity, or delivery."
          },
          "risk_level": {
            "type": "string",
            "enum": [
              "low",
              "medium",
              "high",
              "critical"
            ],
            "description": "Categorical risk assessment."
          },
          "recommendation": {
            "type": "string",
            "description": "Clean, actionable signup gatekeeper directive."
          },
          "evaluation_time_ms": {
            "type": "number",
            "description": "Server-side evaluation time in milliseconds for this request; not an end-to-end API latency guarantee."
          },
          "identity": {
            "type": "object",
            "description": "Canonical identity deduplication object.",
            "properties": {
              "normalized_email": {
                "type": "string",
                "description": "Canonical email (lowercase, stripped Gmail dots and +alias extensions)."
              },
              "fingerprint": {
                "type": "string",
                "description": "SHA-256 cryptographic hash of normalized email for account deduplication and sybil attack blocking."
              },
              "local_part": {
                "type": "string",
                "description": "Base local part."
              },
              "domain": {
                "type": "string",
                "description": "Canonical domain name."
              },
              "has_subaddressing": {
                "type": "boolean",
                "description": "Whether email contains plus-aliasing (e.g. user+tag@gmail.com)."
              },
              "subaddress": {
                "type": "string",
                "nullable": true,
                "description": "The extracted subaddress tag if present, else null."
              },
              "has_dot_stuffing": {
                "type": "boolean",
                "description": "Whether email contains dot stuffing patterns (e.g. u.s.e.r@gmail.com)."
              }
            }
          },
          "classification": {
            "type": "object",
            "description": "Domain and account classification.",
            "properties": {
              "account_type": {
                "type": "string",
                "enum": [
                  "business",
                  "consumer_free",
                  "education",
                  "government",
                  "disposable"
                ],
                "description": "Organizational account category."
              },
              "is_business_email": {
                "type": "boolean",
                "description": "True if domain belongs to a commercial corporate organization."
              },
              "is_free_provider": {
                "type": "boolean",
                "description": "True for consumer webmail (Gmail, Yahoo, Outlook, ProtonMail, etc.)."
              },
              "is_disposable": {
                "type": "boolean",
                "description": "True if provider is a temporary or throwaway inbox service."
              },
              "is_role_account": {
                "type": "boolean",
                "description": "True for generic functional handles (admin@, support@, info@, billing@)."
              },
              "tld_tier": {
                "type": "string",
                "enum": [
                  "premium",
                  "standard",
                  "suspicious"
                ],
                "description": "TLD abuse reputation tier."
              }
            }
          },
          "syntax": {
            "type": "object",
            "description": "RFC 5321 / 5322 syntax validation and auto-correction.",
            "properties": {
              "is_valid_format": {
                "type": "boolean",
                "description": "True if email conforms to RFC standards."
              },
              "did_you_mean": {
                "type": "string",
                "nullable": true,
                "description": "Did-you-mean suggestion for mistyped domains (e.g. `user@gmail.com` for `user@gmial.com`)."
              }
            }
          },
          "email_quality": {
            "type": "object",
            "description": "Local-part quality signals (sanitized production contract).",
            "properties": {
              "score": {
                "type": "integer",
                "description": "Quality score for the username component (0-100)."
              },
              "is_role_account": {
                "type": "boolean",
                "description": "True if handle is a shared organizational role account."
              },
              "has_subaddressing": {
                "type": "boolean",
                "description": "True if subaddress delimiter detected."
              },
              "has_dot_stuffing": {
                "type": "boolean",
                "description": "True if dot stuffing detected."
              }
            }
          },
          "domain_quality": {
            "type": "object",
            "description": "Domain reputation and DomainLedger dynamic maturity.",
            "properties": {
              "score": {
                "type": "integer",
                "description": "Domain quality score (0-100)."
              },
              "domain": {
                "type": "string",
                "description": "Domain evaluated."
              },
              "registered_date": {
                "type": "string",
                "nullable": true,
                "description": "Original domain registration date (YYYY-MM-DD)."
              },
              "registered_at": {
                "type": "integer",
                "nullable": true,
                "description": "Unix epoch timestamp of registration."
              },
              "age_days": {
                "type": "integer",
                "nullable": true,
                "description": "Domain age in days calculated in real-time."
              },
              "provider_type": {
                "type": "string",
                "enum": [
                  "disposable",
                  "public_free",
                  "custom_corporate",
                  "generic_hosted"
                ],
                "description": "Domain infrastructure type."
              },
              "tld_tier": {
                "type": "string",
                "enum": [
                  "premium",
                  "standard",
                  "suspicious"
                ],
                "description": "TLD tier."
              },
              "is_dead": {
                "type": "boolean",
                "description": "True if domain is NXDOMAIN, abandoned, or dropped."
              },
              "is_parked": {
                "type": "boolean",
                "description": "True if domain is parked or holding page."
              },
              "length": {
                "type": "integer",
                "description": "Character length of the domain name."
              },
              "status": {
                "type": "string",
                "enum": [
                  "active",
                  "dead",
                  "parked",
                  "no_mx"
                ],
                "description": "Domain status."
              }
            }
          },
          "dns": {
            "type": "object",
            "description": "Live DNS and mail server routing.",
            "properties": {
              "has_mx": {
                "type": "boolean",
                "description": "True if domain has valid MX or fallback mail exchangers."
              },
              "mx_records": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "List of resolved mail exchanger hosts."
              },
              "vendor": {
                "type": "string",
                "description": "Detected email infrastructure vendor (e.g. Google Workspace, Microsoft 365)."
              },
              "has_spf": {
                "type": "boolean",
                "description": "True if SPF records are configured."
              },
              "has_dmarc": {
                "type": "boolean",
                "description": "True if DMARC policy is published."
              },
              "resolution_status": {
                "type": "string",
                "description": "DNS resolution status code."
              }
            }
          },
          "domain_verdict": {
            "type": "object",
            "description": "Verdict on the domain part alone. Same values `/v1/domain` returns for this domain.",
            "properties": {
              "score": {
                "type": "integer",
                "description": "Domain risk score from 0 to 100."
              },
              "decision": {
                "type": "string",
                "enum": [
                  "allow",
                  "challenge",
                  "deny"
                ],
                "description": "Recommendation for the domain alone: `allow`, `challenge`, or `deny`."
              },
              "risk_level": {
                "type": "string",
                "enum": [
                  "low",
                  "medium",
                  "high",
                  "critical"
                ],
                "description": "Categorical risk assessment for the domain."
              },
              "recommendation": {
                "type": "string",
                "description": "Short explanation of the domain decision."
              },
              "flags": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Domain risk flags (see `/v1/domain` for the list). Empty array for a clean domain."
              },
              "evidence": {
                "type": "string",
                "enum": [
                  "complete",
                  "partial"
                ],
                "description": "`complete` when DNS was looked up. `partial` when it was not, so MX, SPF, and DMARC are unknown."
              }
            }
          },
          "flags": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Security exception and anomaly triggers (e.g. `SUSPICIOUS_HANDLE_PATTERN`, `DISPOSABLE_DOMAIN`, `NO_MX_RECORDS`). Empty array for clean addresses."
          }
        }
      },
      "CheckBulkRequest": {
        "type": "object",
        "properties": {
          "emails": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "required": true,
            "example": [
              "sarah.jenkins@gmail.com",
              "alex@stripe.com",
              "bot@10minutemail.com"
            ],
            "description": "Array of email addresses to clean and score (up to 10,000 per request)."
          },
          "format": {
            "type": "string",
            "required": false,
            "example": "compact",
            "description": "Format selector (batch always outputs compact result rows)."
          },
          "fields": {
            "type": "string",
            "required": false,
            "example": "email,score,decision,fingerprint",
            "description": "Optional field mask."
          }
        }
      },
      "CheckBulkResponse": {
        "type": "object",
        "properties": {
          "total": {
            "type": "integer",
            "description": "Total number of emails received in the batch."
          },
          "processed": {
            "type": "integer",
            "description": "Number of emails successfully evaluated."
          },
          "evaluation_time_ms": {
            "type": "number",
            "description": "Total server-side processing duration in milliseconds."
          },
          "summary": {
            "type": "object",
            "description": "Aggregate classification counts across the batch.",
            "properties": {
              "allow": {
                "type": "integer",
                "description": "Total high-confidence legitimate emails."
              },
              "challenge": {
                "type": "integer",
                "description": "Total moderate-risk / role-based emails."
              },
              "deny": {
                "type": "integer",
                "description": "Total invalid, disposable, or fraudulent emails."
              }
            }
          },
          "results": {
            "type": "array",
            "description": "Per-email evaluation records.",
            "items": {
              "type": "object",
              "properties": {
                "email": {
                  "type": "string",
                  "description": "Original email evaluated."
                },
                "score": {
                  "type": "integer",
                  "description": "Quality score from 0 to 100."
                },
                "decision": {
                  "type": "string",
                  "enum": [
                    "allow",
                    "challenge",
                    "deny"
                  ],
                  "description": "Actionable decision."
                },
                "risk_level": {
                  "type": "string",
                  "enum": [
                    "low",
                    "medium",
                    "high",
                    "critical"
                  ],
                  "description": "Risk category."
                },
                "account_type": {
                  "type": "string",
                  "enum": [
                    "business",
                    "consumer_free",
                    "education",
                    "government",
                    "disposable"
                  ],
                  "description": "Organization category."
                },
                "is_business_email": {
                  "type": "boolean",
                  "description": "True if domain belongs to a commercial enterprise."
                },
                "is_disposable": {
                  "type": "boolean",
                  "description": "True if temporary/burner email provider."
                },
                "did_you_mean": {
                  "type": "string",
                  "nullable": true,
                  "description": "Typo suggestion if domain was mistyped, else null."
                },
                "fingerprint": {
                  "type": "string",
                  "description": "SHA-256 canonical identity hash."
                },
                "flags": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  },
                  "description": "Sanitized public security flags."
                },
                "recommendation": {
                  "type": "string",
                  "description": "Standardized gatekeeper policy recommendation."
                }
              }
            }
          }
        }
      },
      "DomainSingleRequest": {
        "type": "object",
        "properties": {
          "domain": {
            "type": "string",
            "required": true,
            "example": "acme.com",
            "description": "The domain name to score, without a local part or `@`."
          }
        }
      },
      "DomainSingleResponse": {
        "type": "object",
        "properties": {
          "domain": {
            "type": "string",
            "description": "Domain evaluated."
          },
          "score": {
            "type": "integer",
            "description": "Domain risk score from 0 (dead, disposable, or unusable for mail) to 100 (established domain with working mail)."
          },
          "decision": {
            "type": "string",
            "enum": [
              "allow",
              "challenge",
              "deny"
            ],
            "description": "Risk-based policy recommendation: `allow`, `challenge`, or `deny`. It describes the domain only, not any mailbox on it."
          },
          "risk_level": {
            "type": "string",
            "enum": [
              "low",
              "medium",
              "high",
              "critical"
            ],
            "description": "Categorical risk assessment."
          },
          "recommendation": {
            "type": "string",
            "description": "Short explanation of the decision."
          },
          "flags": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Domain risk flags (listed in the endpoint description). Empty array for a clean domain."
          },
          "evidence": {
            "type": "string",
            "enum": [
              "complete",
              "partial"
            ],
            "description": "`complete` when DNS was looked up. `partial` when it was not, so MX, SPF, and DMARC are unknown."
          },
          "did_you_mean": {
            "type": "string",
            "nullable": true,
            "description": "Suggested domain when the input looks like a typo of a known provider (e.g. `gmail.com` for `gmial.com`), else null."
          },
          "evaluation_time_ms": {
            "type": "number",
            "description": "Server-side evaluation time in milliseconds for this request; not an end-to-end API latency guarantee."
          },
          "domain_quality": {
            "type": "object",
            "description": "Domain reputation, registration age, and status.",
            "properties": {
              "score": {
                "type": "integer",
                "description": "Domain quality score (0-100)."
              },
              "domain": {
                "type": "string",
                "description": "Domain evaluated."
              },
              "registered_date": {
                "type": "string",
                "nullable": true,
                "description": "Original domain registration date (YYYY-MM-DD)."
              },
              "registered_at": {
                "type": "integer",
                "nullable": true,
                "description": "Unix epoch timestamp of registration."
              },
              "age_days": {
                "type": "integer",
                "nullable": true,
                "description": "Domain age in days, calculated at request time."
              },
              "provider_type": {
                "type": "string",
                "enum": [
                  "disposable",
                  "public_free",
                  "custom_corporate",
                  "generic_hosted"
                ],
                "description": "Domain infrastructure type."
              },
              "tld_tier": {
                "type": "string",
                "enum": [
                  "premium",
                  "standard",
                  "suspicious"
                ],
                "description": "TLD abuse reputation tier."
              },
              "is_dead": {
                "type": "boolean",
                "description": "True if domain is NXDOMAIN, abandoned, or dropped."
              },
              "is_parked": {
                "type": "boolean",
                "description": "True if domain is parked or a holding page."
              },
              "length": {
                "type": "integer",
                "description": "Character length of the domain name."
              },
              "status": {
                "type": "string",
                "enum": [
                  "active",
                  "dead",
                  "parked",
                  "no_mx"
                ],
                "description": "Domain status."
              }
            }
          },
          "dns": {
            "type": "object",
            "description": "Mail DNS for the domain. Unknown when `evidence` is `partial`.",
            "properties": {
              "has_mx": {
                "type": "boolean",
                "description": "True if domain has valid MX or fallback mail exchangers."
              },
              "mx_records": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "List of resolved mail exchanger hosts."
              },
              "vendor": {
                "type": "string",
                "description": "Detected email infrastructure vendor (e.g. Google Workspace, Microsoft 365)."
              },
              "has_spf": {
                "type": "boolean",
                "description": "True if SPF records are configured."
              },
              "has_dmarc": {
                "type": "boolean",
                "description": "True if DMARC policy is published."
              },
              "resolution_status": {
                "type": "string",
                "description": "DNS resolution status code."
              }
            }
          }
        }
      },
      "DomainBulkRequest": {
        "type": "object",
        "properties": {
          "domains": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "required": true,
            "example": [
              "google.com",
              "gmial.com",
              "not a domain"
            ],
            "description": "Array of domains to score (1 to 10,000 per request). A raw JSON array of strings is also accepted as the whole body."
          }
        }
      },
      "DomainBulkResponse": {
        "type": "object",
        "properties": {
          "total": {
            "type": "integer",
            "description": "Number of domains received in the batch."
          },
          "processed": {
            "type": "integer",
            "description": "Number of domains evaluated."
          },
          "evaluation_time_ms": {
            "type": "number",
            "description": "Total server-side processing duration in milliseconds for the batch."
          },
          "summary": {
            "type": "object",
            "description": "Decision counts across the batch.",
            "properties": {
              "allow": {
                "type": "integer",
                "description": "Domains with an `allow` decision."
              },
              "challenge": {
                "type": "integer",
                "description": "Domains with a `challenge` decision."
              },
              "deny": {
                "type": "integer",
                "description": "Domains with a `deny` decision, including invalid entries."
              }
            }
          },
          "results": {
            "type": "array",
            "description": "Per-domain verdicts in submission order. Each equals the `/v1/domain` result for that domain without `domain_quality`, `dns`, and `evaluation_time_ms`.",
            "items": {
              "type": "object",
              "properties": {
                "domain": {
                  "type": "string",
                  "description": "Normalized domain (trimmed, lowercased, trailing dot removed), or the trimmed input for an invalid entry."
                },
                "score": {
                  "type": "integer",
                  "description": "Domain risk score from 0 to 100."
                },
                "decision": {
                  "type": "string",
                  "enum": [
                    "allow",
                    "challenge",
                    "deny"
                  ],
                  "description": "Recommendation for the domain: `allow`, `challenge`, or `deny`."
                },
                "risk_level": {
                  "type": "string",
                  "enum": [
                    "low",
                    "medium",
                    "high",
                    "critical"
                  ],
                  "description": "Categorical risk assessment."
                },
                "recommendation": {
                  "type": "string",
                  "description": "Short explanation of the decision."
                },
                "flags": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  },
                  "description": "Domain risk flags (listed in the endpoint description). Empty array for a clean domain."
                },
                "evidence": {
                  "type": "string",
                  "enum": [
                    "complete",
                    "partial"
                  ],
                  "description": "`complete` when DNS was looked up. `partial` when it was not, so MX, SPF, and DMARC are unknown."
                },
                "did_you_mean": {
                  "type": "string",
                  "nullable": true,
                  "description": "Suggested domain when the input looks like a typo of a known provider, else null."
                }
              }
            }
          }
        }
      },
      "BounceDiagnoseRequest": {
        "type": "object",
        "properties": {
          "diagnostic": {
            "type": "string",
            "required": true,
            "example": "550 5.1.1 <user@example.com>: Recipient address rejected: User unknown in virtual mailbox table",
            "description": "The raw SMTP response line or error string returned by the receiving mailserver."
          },
          "email": {
            "type": "string",
            "required": false,
            "example": "user@example.com",
            "description": "Optional recipient email address associated with the bounce event."
          }
        }
      },
      "BounceDiagnoseResponse": {
        "type": "object",
        "properties": {
          "diagnostic": {
            "type": "string",
            "required": true,
            "description": "Echo of the input diagnostic string."
          },
          "email": {
            "type": "string",
            "required": false,
            "description": "Associated email address if provided in request."
          },
          "category": {
            "type": "string",
            "required": true,
            "enum": [
              "hard_bounce_user_unknown",
              "soft_bounce_mailbox_full",
              "ip_or_domain_blacklisted",
              "authentication_failure",
              "transient_network_timeout"
            ],
            "description": "Standard RFC deliverability classification."
          },
          "action": {
            "type": "string",
            "required": true,
            "enum": [
              "prune_permanent",
              "retry_transient"
            ],
            "description": "Recommended handling of the supplied failure: review permanent suppression for `prune_permanent`, or retry policy for `retry_transient`."
          },
          "permanent_hard_bounce_probability": {
            "type": "number",
            "required": true,
            "description": "Probability [0.0 to 1.0] that this bounce is an unrecoverable hard bounce."
          },
          "confidence": {
            "type": "number",
            "required": true,
            "description": "Confidence level of category classification."
          },
          "recommendation": {
            "type": "string",
            "required": true,
            "description": "Concrete engineering and deliverability guidance."
          },
          "evaluation_time_ms": {
            "type": "number",
            "required": true,
            "description": "Processing latency in milliseconds."
          }
        }
      },
      "HealthResponse": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "ok",
              "degraded"
            ],
            "description": "Cluster operational health status."
          },
          "service": {
            "type": "string",
            "description": "Engine runtime identifier and major version."
          },
          "domain": {
            "type": "string",
            "description": "Canonical API authority domain."
          },
          "endpoint": {
            "type": "string",
            "description": "Primary email scoring route."
          },
          "capacity": {
            "type": "string",
            "description": "Verified throughput range per single HTTP connection."
          },
          "max_batch_size": {
            "type": "integer",
            "description": "Maximum allowable emails in a single bulk batch request."
          },
          "supported_formats": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Output format projections supported by the engine."
          },
          "sparse_fieldsets": {
            "type": "string",
            "description": "Syntax directive for bitmask sparse field projection."
          },
          "compression": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Supported transparent stream compression algorithms."
          },
          "features": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Active heuristic and database engines in current deployment."
          }
        }
      }
    }
  },
  "paths": {
    "/v1/email": {
      "post": {
        "summary": "Evaluate an email address for quality, risk, and identity signals",
        "description": "Evaluate syntax, domain and DNS signals, disposable-address indicators, and identity patterns.\nReturns a risk score, decision recommendation, and supporting signals for signup screening,\ncontact evaluation, and alias handling. A result does not establish mailbox ownership,\nhuman identity, or successful delivery. Uses 1 credit per address check.\n\nThe domain part of every address is scored by the same check as `/v1/domain`, and that result\nis returned as `domain_verdict`, so the two endpoints never disagree about a domain.",
        "operationId": "check_single",
        "tags": [
          "Core Verification"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "email",
            "in": "query",
            "required": false,
            "description": "Email address to evaluate via GET query parameter (alternative to POST JSON body).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "Set to `compact` for an ultra-fast, flattened 10-field response omitting deep sub-objects.",
            "schema": {
              "type": "string",
              "default": "full",
              "enum": [
                "full",
                "compact"
              ]
            }
          },
          {
            "name": "fields",
            "in": "query",
            "required": false,
            "description": "Comma-separated sparse field projection to minimize payload size and latency.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "cURL",
            "source": "curl -sS -X POST \"https://api.emailscore.io/v1/email\" \\\n  -H \"Authorization: Bearer YOUR_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"email\": \"sarah.jenkins@gmail.com\"}'"
          },
          {
            "lang": "Ruby",
            "label": "Ruby",
            "source": "require 'net/http'\nrequire 'uri'\nrequire 'json'\n\nuri = URI('https://api.emailscore.io/v1/email')\nhttp = Net::HTTP.new(uri.host, uri.port)\nhttp.use_ssl = true\n\nreq = Net::HTTP::Post.new(uri.path, {\n  'Authorization' => 'Bearer YOUR_API_KEY',\n  'Content-Type' => 'application/json'\n})\nreq.body = { email: 'sarah.jenkins@gmail.com' }.to_json\n\nres = http.request(req)\ndata = JSON.parse(res.body)\n\nputs \"Score: #{data['score']}/100 | Decision: #{data['decision'].upcase}\"\nputs \"Normalized: #{data.dig('identity', 'normalized_email')}\"\nputs \"Fingerprint: #{data.dig('identity', 'fingerprint')}\"\nputs \"Recommendation: #{data['recommendation']}\"\n\nif data['decision'] == 'deny'\n  raise \"Signup blocked: #{data['recommendation']}\"\nend"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import requests\n\nurl = \"https://api.emailscore.io/v1/email\"\nheaders = {\n    \"Authorization\": \"Bearer YOUR_API_KEY\",\n    \"Content-Type\": \"application/json\",\n}\npayload = {\"email\": \"sarah.jenkins@gmail.com\"}\n\nresponse = requests.post(url, json=payload, headers=headers)\ndata = response.json()\n\nprint(f\"Email: {data['email']}\")\nprint(f\"Score: {data['score']}/100 -> Decision: {data['decision'].upper()}\")\nprint(f\"Fingerprint: {data['identity']['fingerprint']}\")\nprint(f\"Recommendation: {data['recommendation']}\")"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "// Single Email Check\nconst response = await fetch('https://api.emailscore.io/v1/email', {\n  method: 'POST',\n  headers: {\n    'Authorization': 'Bearer YOUR_API_KEY',\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    email: 'sarah.jenkins@gmail.com'\n  }),\n});\n\nconst result = await response.json();\nconsole.log(`Score: ${result.score}/100 | Decision: ${result.decision}`);\nconsole.log('Normalized Identity:', result.identity.normalized_email);\nconsole.log('Fingerprint:', result.identity.fingerprint);"
          },
          {
            "lang": "Go",
            "label": "Go",
            "source": "package main\n\nimport (\n    \"bytes\"\n    \"fmt\"\n    \"io\"\n    \"net/http\"\n)\n\nfunc main() {\n    url := \"https://api.emailscore.io/v1/email\"\n    payload := []byte(`{\"email\": \"sarah.jenkins@gmail.com\"}`)\n\n    req, err := http.NewRequest(\"POST\", url, bytes.NewBuffer(payload))\n    if err != nil {\n        panic(err)\n    }\n\n    req.Header.Set(\"Authorization\", \"Bearer YOUR_API_KEY\")\n    req.Header.Set(\"Content-Type\", \"application/json\")\n\n    client := &http.Client{}\n    resp, err := client.Do(req)\n    if err != nil {\n        panic(err)\n    }\n    defer resp.Body.Close()\n\n    body, _ := io.ReadAll(resp.Body)\n    fmt.Println(string(body))\n}"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.emailscore.io/v1/email\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_POST, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    'Authorization: Bearer YOUR_API_KEY',\n    'Content-Type: application/json'\n]);\ncurl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([\n    'email' => 'sarah.jenkins@gmail.com'\n]));\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\n$result = json_decode($response, true);\necho \"Score: \" . $result['score'] . \"/100 | Decision: \" . strtoupper($result['decision']) . \"\\n\";\necho \"Fingerprint: \" . $result['identity']['fingerprint'] . \"\\n\";"
          },
          {
            "lang": "Rust",
            "label": "Rust",
            "source": "use reqwest::header::{AUTHORIZATION, CONTENT_TYPE};\nuse serde_json::{json, Value};\n\n#[tokio::main]\nasync fn main() -> Result<(), Box<dyn std::error::Error>> {\n    let client = reqwest::Client::new();\n    let res = client\n        .post(\"https://api.emailscore.io/v1/email\")\n        .header(AUTHORIZATION, \"Bearer YOUR_API_KEY\")\n        .header(CONTENT_TYPE, \"application/json\")\n        .json(&json!({ \"email\": \"sarah.jenkins@gmail.com\" }))\n        .send()\n        .await?;\n\n    let json: Value = res.json().await?;\n    println!(\"Score: {} | Decision: {}\", json[\"score\"], json[\"decision\"]);\n    println!(\"Fingerprint: {}\", json[\"identity\"][\"fingerprint\"]);\n    Ok(())\n}"
          }
        ],
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "cURL",
            "source": "curl -sS -X POST \"https://api.emailscore.io/v1/email\" \\\n  -H \"Authorization: Bearer YOUR_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"email\": \"sarah.jenkins@gmail.com\"}'"
          },
          {
            "lang": "Ruby",
            "label": "Ruby",
            "source": "require 'net/http'\nrequire 'uri'\nrequire 'json'\n\nuri = URI('https://api.emailscore.io/v1/email')\nhttp = Net::HTTP.new(uri.host, uri.port)\nhttp.use_ssl = true\n\nreq = Net::HTTP::Post.new(uri.path, {\n  'Authorization' => 'Bearer YOUR_API_KEY',\n  'Content-Type' => 'application/json'\n})\nreq.body = { email: 'sarah.jenkins@gmail.com' }.to_json\n\nres = http.request(req)\ndata = JSON.parse(res.body)\n\nputs \"Score: #{data['score']}/100 | Decision: #{data['decision'].upcase}\"\nputs \"Normalized: #{data.dig('identity', 'normalized_email')}\"\nputs \"Fingerprint: #{data.dig('identity', 'fingerprint')}\"\nputs \"Recommendation: #{data['recommendation']}\"\n\nif data['decision'] == 'deny'\n  raise \"Signup blocked: #{data['recommendation']}\"\nend"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import requests\n\nurl = \"https://api.emailscore.io/v1/email\"\nheaders = {\n    \"Authorization\": \"Bearer YOUR_API_KEY\",\n    \"Content-Type\": \"application/json\",\n}\npayload = {\"email\": \"sarah.jenkins@gmail.com\"}\n\nresponse = requests.post(url, json=payload, headers=headers)\ndata = response.json()\n\nprint(f\"Email: {data['email']}\")\nprint(f\"Score: {data['score']}/100 -> Decision: {data['decision'].upper()}\")\nprint(f\"Fingerprint: {data['identity']['fingerprint']}\")\nprint(f\"Recommendation: {data['recommendation']}\")"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "// Single Email Check\nconst response = await fetch('https://api.emailscore.io/v1/email', {\n  method: 'POST',\n  headers: {\n    'Authorization': 'Bearer YOUR_API_KEY',\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    email: 'sarah.jenkins@gmail.com'\n  }),\n});\n\nconst result = await response.json();\nconsole.log(`Score: ${result.score}/100 | Decision: ${result.decision}`);\nconsole.log('Normalized Identity:', result.identity.normalized_email);\nconsole.log('Fingerprint:', result.identity.fingerprint);"
          },
          {
            "lang": "Go",
            "label": "Go",
            "source": "package main\n\nimport (\n    \"bytes\"\n    \"fmt\"\n    \"io\"\n    \"net/http\"\n)\n\nfunc main() {\n    url := \"https://api.emailscore.io/v1/email\"\n    payload := []byte(`{\"email\": \"sarah.jenkins@gmail.com\"}`)\n\n    req, err := http.NewRequest(\"POST\", url, bytes.NewBuffer(payload))\n    if err != nil {\n        panic(err)\n    }\n\n    req.Header.Set(\"Authorization\", \"Bearer YOUR_API_KEY\")\n    req.Header.Set(\"Content-Type\", \"application/json\")\n\n    client := &http.Client{}\n    resp, err := client.Do(req)\n    if err != nil {\n        panic(err)\n    }\n    defer resp.Body.Close()\n\n    body, _ := io.ReadAll(resp.Body)\n    fmt.Println(string(body))\n}"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.emailscore.io/v1/email\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_POST, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    'Authorization: Bearer YOUR_API_KEY',\n    'Content-Type: application/json'\n]);\ncurl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([\n    'email' => 'sarah.jenkins@gmail.com'\n]));\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\n$result = json_decode($response, true);\necho \"Score: \" . $result['score'] . \"/100 | Decision: \" . strtoupper($result['decision']) . \"\\n\";\necho \"Fingerprint: \" . $result['identity']['fingerprint'] . \"\\n\";"
          },
          {
            "lang": "Rust",
            "label": "Rust",
            "source": "use reqwest::header::{AUTHORIZATION, CONTENT_TYPE};\nuse serde_json::{json, Value};\n\n#[tokio::main]\nasync fn main() -> Result<(), Box<dyn std::error::Error>> {\n    let client = reqwest::Client::new();\n    let res = client\n        .post(\"https://api.emailscore.io/v1/email\")\n        .header(AUTHORIZATION, \"Bearer YOUR_API_KEY\")\n        .header(CONTENT_TYPE, \"application/json\")\n        .json(&json!({ \"email\": \"sarah.jenkins@gmail.com\" }))\n        .send()\n        .await?;\n\n    let json: Value = res.json().await?;\n    println!(\"Score: {} | Decision: {}\", json[\"score\"], json[\"decision\"]);\n    println!(\"Fingerprint: {}\", json[\"identity\"][\"fingerprint\"]);\n    Ok(())\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful evaluation. Returns complete JSON security dossier.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "email": {
                      "type": "string",
                      "description": "Original email address evaluated."
                    },
                    "local_part": {
                      "type": "string",
                      "description": "Extracted local part (username) before the @ symbol."
                    },
                    "domain": {
                      "type": "string",
                      "description": "Extracted domain name after the @ symbol."
                    },
                    "score": {
                      "type": "integer",
                      "description": "Deterministic quality score from 0 (fraudulent/dead) to 100 (high confidence legitimate)."
                    },
                    "decision": {
                      "type": "string",
                      "enum": [
                        "allow",
                        "challenge",
                        "deny"
                      ],
                      "description": "Risk-based policy recommendation: `allow`, `challenge`, or `deny`. Review supporting signals; this is not proof of ownership, human identity, or delivery."
                    },
                    "risk_level": {
                      "type": "string",
                      "enum": [
                        "low",
                        "medium",
                        "high",
                        "critical"
                      ],
                      "description": "Categorical risk assessment."
                    },
                    "recommendation": {
                      "type": "string",
                      "description": "Clean, actionable signup gatekeeper directive."
                    },
                    "evaluation_time_ms": {
                      "type": "number",
                      "description": "Server-side evaluation time in milliseconds for this request; not an end-to-end API latency guarantee."
                    },
                    "identity": {
                      "type": "object",
                      "description": "Canonical identity deduplication object.",
                      "properties": {
                        "normalized_email": {
                          "type": "string",
                          "description": "Canonical email (lowercase, stripped Gmail dots and +alias extensions)."
                        },
                        "fingerprint": {
                          "type": "string",
                          "description": "SHA-256 cryptographic hash of normalized email for account deduplication and sybil attack blocking."
                        },
                        "local_part": {
                          "type": "string",
                          "description": "Base local part."
                        },
                        "domain": {
                          "type": "string",
                          "description": "Canonical domain name."
                        },
                        "has_subaddressing": {
                          "type": "boolean",
                          "description": "Whether email contains plus-aliasing (e.g. user+tag@gmail.com)."
                        },
                        "subaddress": {
                          "type": "string",
                          "nullable": true,
                          "description": "The extracted subaddress tag if present, else null."
                        },
                        "has_dot_stuffing": {
                          "type": "boolean",
                          "description": "Whether email contains dot stuffing patterns (e.g. u.s.e.r@gmail.com)."
                        }
                      }
                    },
                    "classification": {
                      "type": "object",
                      "description": "Domain and account classification.",
                      "properties": {
                        "account_type": {
                          "type": "string",
                          "enum": [
                            "business",
                            "consumer_free",
                            "education",
                            "government",
                            "disposable"
                          ],
                          "description": "Organizational account category."
                        },
                        "is_business_email": {
                          "type": "boolean",
                          "description": "True if domain belongs to a commercial corporate organization."
                        },
                        "is_free_provider": {
                          "type": "boolean",
                          "description": "True for consumer webmail (Gmail, Yahoo, Outlook, ProtonMail, etc.)."
                        },
                        "is_disposable": {
                          "type": "boolean",
                          "description": "True if provider is a temporary or throwaway inbox service."
                        },
                        "is_role_account": {
                          "type": "boolean",
                          "description": "True for generic functional handles (admin@, support@, info@, billing@)."
                        },
                        "tld_tier": {
                          "type": "string",
                          "enum": [
                            "premium",
                            "standard",
                            "suspicious"
                          ],
                          "description": "TLD abuse reputation tier."
                        }
                      }
                    },
                    "syntax": {
                      "type": "object",
                      "description": "RFC 5321 / 5322 syntax validation and auto-correction.",
                      "properties": {
                        "is_valid_format": {
                          "type": "boolean",
                          "description": "True if email conforms to RFC standards."
                        },
                        "did_you_mean": {
                          "type": "string",
                          "nullable": true,
                          "description": "Did-you-mean suggestion for mistyped domains (e.g. `user@gmail.com` for `user@gmial.com`)."
                        }
                      }
                    },
                    "email_quality": {
                      "type": "object",
                      "description": "Local-part quality signals (sanitized production contract).",
                      "properties": {
                        "score": {
                          "type": "integer",
                          "description": "Quality score for the username component (0-100)."
                        },
                        "is_role_account": {
                          "type": "boolean",
                          "description": "True if handle is a shared organizational role account."
                        },
                        "has_subaddressing": {
                          "type": "boolean",
                          "description": "True if subaddress delimiter detected."
                        },
                        "has_dot_stuffing": {
                          "type": "boolean",
                          "description": "True if dot stuffing detected."
                        }
                      }
                    },
                    "domain_quality": {
                      "type": "object",
                      "description": "Domain reputation and DomainLedger dynamic maturity.",
                      "properties": {
                        "score": {
                          "type": "integer",
                          "description": "Domain quality score (0-100)."
                        },
                        "domain": {
                          "type": "string",
                          "description": "Domain evaluated."
                        },
                        "registered_date": {
                          "type": "string",
                          "nullable": true,
                          "description": "Original domain registration date (YYYY-MM-DD)."
                        },
                        "registered_at": {
                          "type": "integer",
                          "nullable": true,
                          "description": "Unix epoch timestamp of registration."
                        },
                        "age_days": {
                          "type": "integer",
                          "nullable": true,
                          "description": "Domain age in days calculated in real-time."
                        },
                        "provider_type": {
                          "type": "string",
                          "enum": [
                            "disposable",
                            "public_free",
                            "custom_corporate",
                            "generic_hosted"
                          ],
                          "description": "Domain infrastructure type."
                        },
                        "tld_tier": {
                          "type": "string",
                          "enum": [
                            "premium",
                            "standard",
                            "suspicious"
                          ],
                          "description": "TLD tier."
                        },
                        "is_dead": {
                          "type": "boolean",
                          "description": "True if domain is NXDOMAIN, abandoned, or dropped."
                        },
                        "is_parked": {
                          "type": "boolean",
                          "description": "True if domain is parked or holding page."
                        },
                        "length": {
                          "type": "integer",
                          "description": "Character length of the domain name."
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "active",
                            "dead",
                            "parked",
                            "no_mx"
                          ],
                          "description": "Domain status."
                        }
                      }
                    },
                    "dns": {
                      "type": "object",
                      "description": "Live DNS and mail server routing.",
                      "properties": {
                        "has_mx": {
                          "type": "boolean",
                          "description": "True if domain has valid MX or fallback mail exchangers."
                        },
                        "mx_records": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "description": "List of resolved mail exchanger hosts."
                        },
                        "vendor": {
                          "type": "string",
                          "description": "Detected email infrastructure vendor (e.g. Google Workspace, Microsoft 365)."
                        },
                        "has_spf": {
                          "type": "boolean",
                          "description": "True if SPF records are configured."
                        },
                        "has_dmarc": {
                          "type": "boolean",
                          "description": "True if DMARC policy is published."
                        },
                        "resolution_status": {
                          "type": "string",
                          "description": "DNS resolution status code."
                        }
                      }
                    },
                    "domain_verdict": {
                      "type": "object",
                      "description": "Verdict on the domain part alone. Same values `/v1/domain` returns for this domain.",
                      "properties": {
                        "score": {
                          "type": "integer",
                          "description": "Domain risk score from 0 to 100."
                        },
                        "decision": {
                          "type": "string",
                          "enum": [
                            "allow",
                            "challenge",
                            "deny"
                          ],
                          "description": "Recommendation for the domain alone: `allow`, `challenge`, or `deny`."
                        },
                        "risk_level": {
                          "type": "string",
                          "enum": [
                            "low",
                            "medium",
                            "high",
                            "critical"
                          ],
                          "description": "Categorical risk assessment for the domain."
                        },
                        "recommendation": {
                          "type": "string",
                          "description": "Short explanation of the domain decision."
                        },
                        "flags": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "description": "Domain risk flags (see `/v1/domain` for the list). Empty array for a clean domain."
                        },
                        "evidence": {
                          "type": "string",
                          "enum": [
                            "complete",
                            "partial"
                          ],
                          "description": "`complete` when DNS was looked up. `partial` when it was not, so MX, SPF, and DMARC are unknown."
                        }
                      }
                    },
                    "flags": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Security exception and anomaly triggers (e.g. `SUSPICIOUS_HANDLE_PATTERN`, `DISPOSABLE_DOMAIN`, `NO_MX_RECORDS`). Empty array for clean addresses."
                    }
                  }
                },
                "example": {
                  "email": "sarah.jenkins@gmail.com",
                  "local_part": "sarah.jenkins",
                  "domain": "gmail.com",
                  "score": 92,
                  "decision": "allow",
                  "risk_level": "low",
                  "recommendation": "Allow signup: high confidence legitimate user.",
                  "evaluation_time_ms": 0.28,
                  "identity": {
                    "normalized_email": "sarahjenkins@gmail.com",
                    "fingerprint": "8f462664790604f97eab4b104d580d8f824c643038b600a96115bf4014194071",
                    "local_part": "sarah.jenkins",
                    "domain": "gmail.com",
                    "has_subaddressing": false,
                    "subaddress": null,
                    "has_dot_stuffing": false
                  },
                  "classification": {
                    "account_type": "consumer_free",
                    "is_business_email": false,
                    "is_free_provider": true,
                    "is_disposable": false,
                    "is_role_account": false,
                    "tld_tier": "standard"
                  },
                  "syntax": {
                    "is_valid_format": true,
                    "did_you_mean": null
                  },
                  "email_quality": {
                    "score": 95,
                    "is_role_account": false,
                    "has_subaddressing": false,
                    "has_dot_stuffing": false
                  },
                  "domain_quality": {
                    "score": 98,
                    "domain": "gmail.com",
                    "registered_date": "1995-08-13",
                    "registered_at": 874281600,
                    "age_days": 10592,
                    "provider_type": "public_free",
                    "tld_tier": "premium",
                    "is_dead": false,
                    "is_parked": false,
                    "length": 9,
                    "status": "active"
                  },
                  "dns": {
                    "has_mx": true,
                    "mx_records": [
                      "gmail-smtp-in.l.google.com"
                    ],
                    "vendor": "Google (Gmail Consumer)",
                    "has_spf": true,
                    "has_dmarc": true,
                    "resolution_status": "resolved"
                  },
                  "domain_verdict": {
                    "score": 99,
                    "decision": "allow",
                    "risk_level": "low",
                    "recommendation": "Allow: established domain with working mail.",
                    "flags": [],
                    "evidence": "complete"
                  },
                  "flags": []
                }
              }
            }
          },
          "400": {
            "description": "Malformed request, missing email field, or invalid syntax.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Reason the evaluation failed."
                    }
                  }
                },
                "example": {
                  "error": "Email address cannot be empty"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Authentication error message."
                    }
                  }
                },
                "example": {
                  "error": "Invalid or revoked API key"
                }
              }
            }
          },
          "429": {
            "description": "Two causes. `rate_limited`: more requests per second than your plan allows. The limit applies to your whole account, across all its API keys; the response carries `Retry-After` (seconds) and `X-Request-Rate-Limit`, and the request uses no credits. Quota: a free Developer allowance is used up with no credit pack balance (paid plans are never blocked by quota; checks past the allowance are billed at the plan's rate).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "`rate_limited`, or a message describing the exhausted allowance."
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable explanation, including when to retry."
                    },
                    "requests_per_second": {
                      "type": "integer",
                      "description": "Your plan's request rate (present when `error` is `rate_limited`)."
                    }
                  }
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Request rate limit reached: 25 requests per second. Retry after 1 second. Bulk endpoints check up to 10000 items in one request.",
                  "requests_per_second": 25
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string",
                    "required": true,
                    "example": "sarah.jenkins@gmail.com",
                    "description": "The raw email address to score."
                  },
                  "format": {
                    "type": "string",
                    "required": false,
                    "example": "full",
                    "description": "Optional format override in request body (`full` or `compact`)."
                  },
                  "fields": {
                    "type": "string",
                    "required": false,
                    "example": "score,decision,identity.normalized_email",
                    "description": "Optional sparse field projection override in request body."
                  }
                }
              },
              "example": {
                "email": "sarah.jenkins@gmail.com"
              }
            }
          }
        }
      }
    },
    "/v1/email/bulk": {
      "post": {
        "summary": "Screen and score a batch of email addresses",
        "description": "Screen contact lists for address-quality and risk signals. Returns summary statistics\nand per-address results for review and further verification decisions. Batch results\ndo not confirm mailbox ownership or guarantee delivery. Uses 1 credit per address check.",
        "operationId": "check_bulk",
        "tags": [
          "Core Verification"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "fields",
            "in": "query",
            "required": false,
            "description": "Optional sparse fieldset projection to minimize response payload bandwidth.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "cURL",
            "source": "curl -sS -X POST \"https://api.emailscore.io/v1/email/bulk\" \\\n  -H \"Authorization: Bearer YOUR_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Accept-Encoding: gzip\" \\\n  -d '{\"emails\": [\"sarah.jenkins@gmail.com\", \"alex@stripe.com\", \"bot@10minutemail.com\"]}'"
          },
          {
            "lang": "Ruby",
            "label": "Ruby",
            "source": "require 'net/http'\nrequire 'uri'\nrequire 'json'\n\nuri = URI('https://api.emailscore.io/v1/email/bulk')\nhttp = Net::HTTP.new(uri.host, uri.port)\nhttp.use_ssl = true\n\nreq = Net::HTTP::Post.new(uri.path, {\n  'Authorization' => 'Bearer YOUR_API_KEY',\n  'Content-Type' => 'application/json',\n  'Accept-Encoding' => 'gzip'\n})\nreq.body = {\n  emails: [\n    'sarah.jenkins@gmail.com',\n    'alex@stripe.com',\n    'bot@10minutemail.com'\n  ]\n}.to_json\n\nres = http.request(req)\nbatch = JSON.parse(res.body)\n\nputs \"Verified #{batch['processed']}/#{batch['total']} in #{batch['evaluation_time_ms']}ms\"\nputs \"Summary: Allow=#{batch.dig('summary', 'allow')}, Deny=#{batch.dig('summary', 'deny')}\"\n\nbatch['results'].each do |item|\n  puts \"  [#{item['decision'].upcase}] #{item['email']} -> Score: #{item['score']}\"\nend"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import requests\n\nurl = \"https://api.emailscore.io/v1/email/bulk\"\nheaders = {\n    \"Authorization\": \"Bearer YOUR_API_KEY\",\n    \"Content-Type\": \"application/json\",\n    \"Accept-Encoding\": \"gzip\",\n}\npayload = {\n    \"emails\": [\n        \"sarah.jenkins@gmail.com\",\n        \"alex@stripe.com\",\n        \"bot@10minutemail.com\",\n    ]\n}\n\nresponse = requests.post(url, json=payload, headers=headers)\ndata = response.json()\n\nprint(f\"Total: {data['total']} | Evaluation Time: {data['evaluation_time_ms']}ms\")\nprint(f\"Summary: Allow={data['summary']['allow']}, Deny={data['summary']['deny']}\")\nfor item in data['results']:\n    print(f\" - {item['email']}: {item['score']} ({item['decision']})\")"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "// Bulk / Batch Email Check (Up to 10,000 emails in parallel)\nconst response = await fetch('https://api.emailscore.io/v1/email/bulk', {\n  method: 'POST',\n  headers: {\n    'Authorization': 'Bearer YOUR_API_KEY',\n    'Content-Type': 'application/json',\n    'Accept-Encoding': 'gzip',\n  },\n  body: JSON.stringify({\n    emails: [\n      'sarah.jenkins@gmail.com',\n      'alex@stripe.com',\n      'bot@10minutemail.com',\n    ]\n  }),\n});\n\nconst batch = await response.json();\nconsole.log(`Verified ${batch.processed}/${batch.total} in ${batch.evaluation_time_ms}ms`);\nconsole.log('Summary:', batch.summary); // { allow: 2, challenge: 0, deny: 1 }"
          },
          {
            "lang": "Go",
            "label": "Go",
            "source": "package main\n\nimport (\n    \"bytes\"\n    \"fmt\"\n    \"io\"\n    \"net/http\"\n)\n\nfunc main() {\n    url := \"https://api.emailscore.io/v1/email/bulk\"\n    payload := []byte(`{\"emails\": [\"sarah.jenkins@gmail.com\", \"alex@stripe.com\", \"bot@10minutemail.com\"]}`)\n\n    req, err := http.NewRequest(\"POST\", url, bytes.NewBuffer(payload))\n    if err != nil {\n        panic(err)\n    }\n\n    req.Header.Set(\"Authorization\", \"Bearer YOUR_API_KEY\")\n    req.Header.Set(\"Content-Type\", \"application/json\")\n    req.Header.Set(\"Accept-Encoding\", \"gzip\")\n\n    client := &http.Client{}\n    resp, err := client.Do(req)\n    if err != nil {\n        panic(err)\n    }\n    defer resp.Body.Close()\n\n    body, _ := io.ReadAll(resp.Body)\n    fmt.Println(string(body))\n}"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.emailscore.io/v1/email/bulk\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_POST, true);\ncurl_setopt($ch, CURLOPT_ENCODING, \"gzip\");\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    'Authorization: Bearer YOUR_API_KEY',\n    'Content-Type: application/json',\n    'Accept-Encoding: gzip'\n]);\ncurl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([\n    'emails' => [\n        'sarah.jenkins@gmail.com',\n        'alex@stripe.com',\n        'bot@10minutemail.com'\n    ]\n]));\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\n$batch = json_decode($response, true);\necho \"Verified \" . $batch['processed'] . \"/\" . $batch['total'] . \" in \" . $batch['evaluation_time_ms'] . \"ms\\n\";"
          },
          {
            "lang": "Rust",
            "label": "Rust",
            "source": "use reqwest::header::{ACCEPT_ENCODING, AUTHORIZATION, CONTENT_TYPE};\nuse serde_json::{json, Value};\n\n#[tokio::main]\nasync fn main() -> Result<(), Box<dyn std::error::Error>> {\n    let client = reqwest::Client::new();\n    let res = client\n        .post(\"https://api.emailscore.io/v1/email/bulk\")\n        .header(AUTHORIZATION, \"Bearer YOUR_API_KEY\")\n        .header(CONTENT_TYPE, \"application/json\")\n        .header(ACCEPT_ENCODING, \"gzip\")\n        .json(&json!({\n            \"emails\": [\n                \"sarah.jenkins@gmail.com\",\n                \"alex@stripe.com\",\n                \"bot@10minutemail.com\"\n            ]\n        }))\n        .send()\n        .await?;\n\n    let batch: Value = res.json().await?;\n    println!(\"Processed: {}/{}\", batch[\"processed\"], batch[\"total\"]);\n    println!(\"Summary: {}\", batch[\"summary\"]);\n    Ok(())\n}"
          }
        ],
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "cURL",
            "source": "curl -sS -X POST \"https://api.emailscore.io/v1/email/bulk\" \\\n  -H \"Authorization: Bearer YOUR_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Accept-Encoding: gzip\" \\\n  -d '{\"emails\": [\"sarah.jenkins@gmail.com\", \"alex@stripe.com\", \"bot@10minutemail.com\"]}'"
          },
          {
            "lang": "Ruby",
            "label": "Ruby",
            "source": "require 'net/http'\nrequire 'uri'\nrequire 'json'\n\nuri = URI('https://api.emailscore.io/v1/email/bulk')\nhttp = Net::HTTP.new(uri.host, uri.port)\nhttp.use_ssl = true\n\nreq = Net::HTTP::Post.new(uri.path, {\n  'Authorization' => 'Bearer YOUR_API_KEY',\n  'Content-Type' => 'application/json',\n  'Accept-Encoding' => 'gzip'\n})\nreq.body = {\n  emails: [\n    'sarah.jenkins@gmail.com',\n    'alex@stripe.com',\n    'bot@10minutemail.com'\n  ]\n}.to_json\n\nres = http.request(req)\nbatch = JSON.parse(res.body)\n\nputs \"Verified #{batch['processed']}/#{batch['total']} in #{batch['evaluation_time_ms']}ms\"\nputs \"Summary: Allow=#{batch.dig('summary', 'allow')}, Deny=#{batch.dig('summary', 'deny')}\"\n\nbatch['results'].each do |item|\n  puts \"  [#{item['decision'].upcase}] #{item['email']} -> Score: #{item['score']}\"\nend"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import requests\n\nurl = \"https://api.emailscore.io/v1/email/bulk\"\nheaders = {\n    \"Authorization\": \"Bearer YOUR_API_KEY\",\n    \"Content-Type\": \"application/json\",\n    \"Accept-Encoding\": \"gzip\",\n}\npayload = {\n    \"emails\": [\n        \"sarah.jenkins@gmail.com\",\n        \"alex@stripe.com\",\n        \"bot@10minutemail.com\",\n    ]\n}\n\nresponse = requests.post(url, json=payload, headers=headers)\ndata = response.json()\n\nprint(f\"Total: {data['total']} | Evaluation Time: {data['evaluation_time_ms']}ms\")\nprint(f\"Summary: Allow={data['summary']['allow']}, Deny={data['summary']['deny']}\")\nfor item in data['results']:\n    print(f\" - {item['email']}: {item['score']} ({item['decision']})\")"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "// Bulk / Batch Email Check (Up to 10,000 emails in parallel)\nconst response = await fetch('https://api.emailscore.io/v1/email/bulk', {\n  method: 'POST',\n  headers: {\n    'Authorization': 'Bearer YOUR_API_KEY',\n    'Content-Type': 'application/json',\n    'Accept-Encoding': 'gzip',\n  },\n  body: JSON.stringify({\n    emails: [\n      'sarah.jenkins@gmail.com',\n      'alex@stripe.com',\n      'bot@10minutemail.com',\n    ]\n  }),\n});\n\nconst batch = await response.json();\nconsole.log(`Verified ${batch.processed}/${batch.total} in ${batch.evaluation_time_ms}ms`);\nconsole.log('Summary:', batch.summary); // { allow: 2, challenge: 0, deny: 1 }"
          },
          {
            "lang": "Go",
            "label": "Go",
            "source": "package main\n\nimport (\n    \"bytes\"\n    \"fmt\"\n    \"io\"\n    \"net/http\"\n)\n\nfunc main() {\n    url := \"https://api.emailscore.io/v1/email/bulk\"\n    payload := []byte(`{\"emails\": [\"sarah.jenkins@gmail.com\", \"alex@stripe.com\", \"bot@10minutemail.com\"]}`)\n\n    req, err := http.NewRequest(\"POST\", url, bytes.NewBuffer(payload))\n    if err != nil {\n        panic(err)\n    }\n\n    req.Header.Set(\"Authorization\", \"Bearer YOUR_API_KEY\")\n    req.Header.Set(\"Content-Type\", \"application/json\")\n    req.Header.Set(\"Accept-Encoding\", \"gzip\")\n\n    client := &http.Client{}\n    resp, err := client.Do(req)\n    if err != nil {\n        panic(err)\n    }\n    defer resp.Body.Close()\n\n    body, _ := io.ReadAll(resp.Body)\n    fmt.Println(string(body))\n}"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.emailscore.io/v1/email/bulk\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_POST, true);\ncurl_setopt($ch, CURLOPT_ENCODING, \"gzip\");\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    'Authorization: Bearer YOUR_API_KEY',\n    'Content-Type: application/json',\n    'Accept-Encoding: gzip'\n]);\ncurl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([\n    'emails' => [\n        'sarah.jenkins@gmail.com',\n        'alex@stripe.com',\n        'bot@10minutemail.com'\n    ]\n]));\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\n$batch = json_decode($response, true);\necho \"Verified \" . $batch['processed'] . \"/\" . $batch['total'] . \" in \" . $batch['evaluation_time_ms'] . \"ms\\n\";"
          },
          {
            "lang": "Rust",
            "label": "Rust",
            "source": "use reqwest::header::{ACCEPT_ENCODING, AUTHORIZATION, CONTENT_TYPE};\nuse serde_json::{json, Value};\n\n#[tokio::main]\nasync fn main() -> Result<(), Box<dyn std::error::Error>> {\n    let client = reqwest::Client::new();\n    let res = client\n        .post(\"https://api.emailscore.io/v1/email/bulk\")\n        .header(AUTHORIZATION, \"Bearer YOUR_API_KEY\")\n        .header(CONTENT_TYPE, \"application/json\")\n        .header(ACCEPT_ENCODING, \"gzip\")\n        .json(&json!({\n            \"emails\": [\n                \"sarah.jenkins@gmail.com\",\n                \"alex@stripe.com\",\n                \"bot@10minutemail.com\"\n            ]\n        }))\n        .send()\n        .await?;\n\n    let batch: Value = res.json().await?;\n    println!(\"Processed: {}/{}\", batch[\"processed\"], batch[\"total\"]);\n    println!(\"Summary: {}\", batch[\"summary\"]);\n    Ok(())\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "Batch completed successfully. Returns summary statistics and per-address screening results.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "total": {
                      "type": "integer",
                      "description": "Total number of emails received in the batch."
                    },
                    "processed": {
                      "type": "integer",
                      "description": "Number of emails successfully evaluated."
                    },
                    "evaluation_time_ms": {
                      "type": "number",
                      "description": "Total server-side processing duration in milliseconds."
                    },
                    "summary": {
                      "type": "object",
                      "description": "Aggregate classification counts across the batch.",
                      "properties": {
                        "allow": {
                          "type": "integer",
                          "description": "Total high-confidence legitimate emails."
                        },
                        "challenge": {
                          "type": "integer",
                          "description": "Total moderate-risk / role-based emails."
                        },
                        "deny": {
                          "type": "integer",
                          "description": "Total invalid, disposable, or fraudulent emails."
                        }
                      }
                    },
                    "results": {
                      "type": "array",
                      "description": "Per-email evaluation records.",
                      "items": {
                        "type": "object",
                        "properties": {
                          "email": {
                            "type": "string",
                            "description": "Original email evaluated."
                          },
                          "score": {
                            "type": "integer",
                            "description": "Quality score from 0 to 100."
                          },
                          "decision": {
                            "type": "string",
                            "enum": [
                              "allow",
                              "challenge",
                              "deny"
                            ],
                            "description": "Actionable decision."
                          },
                          "risk_level": {
                            "type": "string",
                            "enum": [
                              "low",
                              "medium",
                              "high",
                              "critical"
                            ],
                            "description": "Risk category."
                          },
                          "account_type": {
                            "type": "string",
                            "enum": [
                              "business",
                              "consumer_free",
                              "education",
                              "government",
                              "disposable"
                            ],
                            "description": "Organization category."
                          },
                          "is_business_email": {
                            "type": "boolean",
                            "description": "True if domain belongs to a commercial enterprise."
                          },
                          "is_disposable": {
                            "type": "boolean",
                            "description": "True if temporary/burner email provider."
                          },
                          "did_you_mean": {
                            "type": "string",
                            "nullable": true,
                            "description": "Typo suggestion if domain was mistyped, else null."
                          },
                          "fingerprint": {
                            "type": "string",
                            "description": "SHA-256 canonical identity hash."
                          },
                          "flags": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            },
                            "description": "Sanitized public security flags."
                          },
                          "recommendation": {
                            "type": "string",
                            "description": "Standardized gatekeeper policy recommendation."
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "total": 3,
                  "processed": 3,
                  "evaluation_time_ms": 1.42,
                  "summary": {
                    "allow": 2,
                    "challenge": 0,
                    "deny": 1
                  },
                  "results": [
                    {
                      "email": "sarah.jenkins@gmail.com",
                      "score": 92,
                      "decision": "allow",
                      "risk_level": "low",
                      "account_type": "consumer_free",
                      "is_business_email": false,
                      "is_disposable": false,
                      "did_you_mean": null,
                      "fingerprint": "8f462664790604f97eab4b104d580d8f824c643038b600a96115bf4014194071",
                      "flags": [],
                      "recommendation": "Allow signup: high confidence legitimate user."
                    },
                    {
                      "email": "alex@stripe.com",
                      "score": 98,
                      "decision": "allow",
                      "risk_level": "low",
                      "account_type": "business",
                      "is_business_email": true,
                      "is_disposable": false,
                      "did_you_mean": null,
                      "fingerprint": "207a9dc3e6aa00898ec0ffbeec946e382cc094bc028f0ee0434407b46618e4bc",
                      "flags": [],
                      "recommendation": "Allow signup: high confidence legitimate user."
                    },
                    {
                      "email": "bot@10minutemail.com",
                      "score": 0,
                      "decision": "deny",
                      "risk_level": "critical",
                      "account_type": "disposable",
                      "is_business_email": false,
                      "is_disposable": true,
                      "did_you_mean": null,
                      "fingerprint": "e57ff311c15b13e90b8f056d3cff4c980387b32a265691079d3be4737d26bbad",
                      "flags": [
                        "DISPOSABLE_DOMAIN"
                      ],
                      "recommendation": "Deny signup: disposable or temporary email addresses are not accepted."
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Emails array cannot be empty or invalid request body.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Batch validation error message."
                    }
                  }
                },
                "example": {
                  "error": "Emails array cannot be empty"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Authentication failure reason."
                    }
                  }
                },
                "example": {
                  "error": "Invalid or revoked API key"
                }
              }
            }
          },
          "429": {
            "description": "Two causes. `rate_limited`: more requests per second than your plan allows. The limit applies to your whole account, across all its API keys; the response carries `Retry-After` (seconds) and `X-Request-Rate-Limit`, and the request uses no credits. Quota: a free Developer allowance is used up with no credit pack balance (paid plans are never blocked by quota; checks past the allowance are billed at the plan's rate).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "`rate_limited`, or a message describing the exhausted allowance."
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable explanation, including when to retry."
                    },
                    "requests_per_second": {
                      "type": "integer",
                      "description": "Your plan's request rate (present when `error` is `rate_limited`)."
                    }
                  }
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Request rate limit reached: 25 requests per second. Retry after 1 second. Bulk endpoints check up to 10000 items in one request.",
                  "requests_per_second": 25
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "emails": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "required": true,
                    "example": [
                      "sarah.jenkins@gmail.com",
                      "alex@stripe.com",
                      "bot@10minutemail.com"
                    ],
                    "description": "Array of email addresses to clean and score (up to 10,000 per request)."
                  },
                  "format": {
                    "type": "string",
                    "required": false,
                    "example": "compact",
                    "description": "Format selector (batch always outputs compact result rows)."
                  },
                  "fields": {
                    "type": "string",
                    "required": false,
                    "example": "email,score,decision,fingerprint",
                    "description": "Optional field mask."
                  }
                }
              },
              "example": {
                "emails": [
                  "sarah.jenkins@gmail.com",
                  "alex@stripe.com",
                  "bot@10minutemail.com"
                ]
              }
            }
          }
        }
      }
    },
    "/v1/email/batch": {
      "post": {
        "summary": "Screen and score a batch of email addresses (Alias)",
        "description": "Screen contact lists for address-quality and risk signals. Returns summary statistics\nand per-address results for review and further verification decisions. Batch results\ndo not confirm mailbox ownership or guarantee delivery. Uses 1 credit per address check.",
        "operationId": "check_bulk_alias",
        "tags": [
          "Core Verification"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "fields",
            "in": "query",
            "required": false,
            "description": "Optional sparse fieldset projection to minimize response payload bandwidth.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "cURL",
            "source": "curl -sS -X POST \"https://api.emailscore.io/v1/email/bulk\" \\\n  -H \"Authorization: Bearer YOUR_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Accept-Encoding: gzip\" \\\n  -d '{\"emails\": [\"sarah.jenkins@gmail.com\", \"alex@stripe.com\", \"bot@10minutemail.com\"]}'"
          },
          {
            "lang": "Ruby",
            "label": "Ruby",
            "source": "require 'net/http'\nrequire 'uri'\nrequire 'json'\n\nuri = URI('https://api.emailscore.io/v1/email/bulk')\nhttp = Net::HTTP.new(uri.host, uri.port)\nhttp.use_ssl = true\n\nreq = Net::HTTP::Post.new(uri.path, {\n  'Authorization' => 'Bearer YOUR_API_KEY',\n  'Content-Type' => 'application/json',\n  'Accept-Encoding' => 'gzip'\n})\nreq.body = {\n  emails: [\n    'sarah.jenkins@gmail.com',\n    'alex@stripe.com',\n    'bot@10minutemail.com'\n  ]\n}.to_json\n\nres = http.request(req)\nbatch = JSON.parse(res.body)\n\nputs \"Verified #{batch['processed']}/#{batch['total']} in #{batch['evaluation_time_ms']}ms\"\nputs \"Summary: Allow=#{batch.dig('summary', 'allow')}, Deny=#{batch.dig('summary', 'deny')}\"\n\nbatch['results'].each do |item|\n  puts \"  [#{item['decision'].upcase}] #{item['email']} -> Score: #{item['score']}\"\nend"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import requests\n\nurl = \"https://api.emailscore.io/v1/email/bulk\"\nheaders = {\n    \"Authorization\": \"Bearer YOUR_API_KEY\",\n    \"Content-Type\": \"application/json\",\n    \"Accept-Encoding\": \"gzip\",\n}\npayload = {\n    \"emails\": [\n        \"sarah.jenkins@gmail.com\",\n        \"alex@stripe.com\",\n        \"bot@10minutemail.com\",\n    ]\n}\n\nresponse = requests.post(url, json=payload, headers=headers)\ndata = response.json()\n\nprint(f\"Total: {data['total']} | Evaluation Time: {data['evaluation_time_ms']}ms\")\nprint(f\"Summary: Allow={data['summary']['allow']}, Deny={data['summary']['deny']}\")\nfor item in data['results']:\n    print(f\" - {item['email']}: {item['score']} ({item['decision']})\")"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "// Bulk / Batch Email Check (Up to 10,000 emails in parallel)\nconst response = await fetch('https://api.emailscore.io/v1/email/bulk', {\n  method: 'POST',\n  headers: {\n    'Authorization': 'Bearer YOUR_API_KEY',\n    'Content-Type': 'application/json',\n    'Accept-Encoding': 'gzip',\n  },\n  body: JSON.stringify({\n    emails: [\n      'sarah.jenkins@gmail.com',\n      'alex@stripe.com',\n      'bot@10minutemail.com',\n    ]\n  }),\n});\n\nconst batch = await response.json();\nconsole.log(`Verified ${batch.processed}/${batch.total} in ${batch.evaluation_time_ms}ms`);\nconsole.log('Summary:', batch.summary); // { allow: 2, challenge: 0, deny: 1 }"
          },
          {
            "lang": "Go",
            "label": "Go",
            "source": "package main\n\nimport (\n    \"bytes\"\n    \"fmt\"\n    \"io\"\n    \"net/http\"\n)\n\nfunc main() {\n    url := \"https://api.emailscore.io/v1/email/bulk\"\n    payload := []byte(`{\"emails\": [\"sarah.jenkins@gmail.com\", \"alex@stripe.com\", \"bot@10minutemail.com\"]}`)\n\n    req, err := http.NewRequest(\"POST\", url, bytes.NewBuffer(payload))\n    if err != nil {\n        panic(err)\n    }\n\n    req.Header.Set(\"Authorization\", \"Bearer YOUR_API_KEY\")\n    req.Header.Set(\"Content-Type\", \"application/json\")\n    req.Header.Set(\"Accept-Encoding\", \"gzip\")\n\n    client := &http.Client{}\n    resp, err := client.Do(req)\n    if err != nil {\n        panic(err)\n    }\n    defer resp.Body.Close()\n\n    body, _ := io.ReadAll(resp.Body)\n    fmt.Println(string(body))\n}"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.emailscore.io/v1/email/bulk\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_POST, true);\ncurl_setopt($ch, CURLOPT_ENCODING, \"gzip\");\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    'Authorization: Bearer YOUR_API_KEY',\n    'Content-Type: application/json',\n    'Accept-Encoding: gzip'\n]);\ncurl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([\n    'emails' => [\n        'sarah.jenkins@gmail.com',\n        'alex@stripe.com',\n        'bot@10minutemail.com'\n    ]\n]));\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\n$batch = json_decode($response, true);\necho \"Verified \" . $batch['processed'] . \"/\" . $batch['total'] . \" in \" . $batch['evaluation_time_ms'] . \"ms\\n\";"
          },
          {
            "lang": "Rust",
            "label": "Rust",
            "source": "use reqwest::header::{ACCEPT_ENCODING, AUTHORIZATION, CONTENT_TYPE};\nuse serde_json::{json, Value};\n\n#[tokio::main]\nasync fn main() -> Result<(), Box<dyn std::error::Error>> {\n    let client = reqwest::Client::new();\n    let res = client\n        .post(\"https://api.emailscore.io/v1/email/bulk\")\n        .header(AUTHORIZATION, \"Bearer YOUR_API_KEY\")\n        .header(CONTENT_TYPE, \"application/json\")\n        .header(ACCEPT_ENCODING, \"gzip\")\n        .json(&json!({\n            \"emails\": [\n                \"sarah.jenkins@gmail.com\",\n                \"alex@stripe.com\",\n                \"bot@10minutemail.com\"\n            ]\n        }))\n        .send()\n        .await?;\n\n    let batch: Value = res.json().await?;\n    println!(\"Processed: {}/{}\", batch[\"processed\"], batch[\"total\"]);\n    println!(\"Summary: {}\", batch[\"summary\"]);\n    Ok(())\n}"
          }
        ],
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "cURL",
            "source": "curl -sS -X POST \"https://api.emailscore.io/v1/email/bulk\" \\\n  -H \"Authorization: Bearer YOUR_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Accept-Encoding: gzip\" \\\n  -d '{\"emails\": [\"sarah.jenkins@gmail.com\", \"alex@stripe.com\", \"bot@10minutemail.com\"]}'"
          },
          {
            "lang": "Ruby",
            "label": "Ruby",
            "source": "require 'net/http'\nrequire 'uri'\nrequire 'json'\n\nuri = URI('https://api.emailscore.io/v1/email/bulk')\nhttp = Net::HTTP.new(uri.host, uri.port)\nhttp.use_ssl = true\n\nreq = Net::HTTP::Post.new(uri.path, {\n  'Authorization' => 'Bearer YOUR_API_KEY',\n  'Content-Type' => 'application/json',\n  'Accept-Encoding' => 'gzip'\n})\nreq.body = {\n  emails: [\n    'sarah.jenkins@gmail.com',\n    'alex@stripe.com',\n    'bot@10minutemail.com'\n  ]\n}.to_json\n\nres = http.request(req)\nbatch = JSON.parse(res.body)\n\nputs \"Verified #{batch['processed']}/#{batch['total']} in #{batch['evaluation_time_ms']}ms\"\nputs \"Summary: Allow=#{batch.dig('summary', 'allow')}, Deny=#{batch.dig('summary', 'deny')}\"\n\nbatch['results'].each do |item|\n  puts \"  [#{item['decision'].upcase}] #{item['email']} -> Score: #{item['score']}\"\nend"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import requests\n\nurl = \"https://api.emailscore.io/v1/email/bulk\"\nheaders = {\n    \"Authorization\": \"Bearer YOUR_API_KEY\",\n    \"Content-Type\": \"application/json\",\n    \"Accept-Encoding\": \"gzip\",\n}\npayload = {\n    \"emails\": [\n        \"sarah.jenkins@gmail.com\",\n        \"alex@stripe.com\",\n        \"bot@10minutemail.com\",\n    ]\n}\n\nresponse = requests.post(url, json=payload, headers=headers)\ndata = response.json()\n\nprint(f\"Total: {data['total']} | Evaluation Time: {data['evaluation_time_ms']}ms\")\nprint(f\"Summary: Allow={data['summary']['allow']}, Deny={data['summary']['deny']}\")\nfor item in data['results']:\n    print(f\" - {item['email']}: {item['score']} ({item['decision']})\")"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "// Bulk / Batch Email Check (Up to 10,000 emails in parallel)\nconst response = await fetch('https://api.emailscore.io/v1/email/bulk', {\n  method: 'POST',\n  headers: {\n    'Authorization': 'Bearer YOUR_API_KEY',\n    'Content-Type': 'application/json',\n    'Accept-Encoding': 'gzip',\n  },\n  body: JSON.stringify({\n    emails: [\n      'sarah.jenkins@gmail.com',\n      'alex@stripe.com',\n      'bot@10minutemail.com',\n    ]\n  }),\n});\n\nconst batch = await response.json();\nconsole.log(`Verified ${batch.processed}/${batch.total} in ${batch.evaluation_time_ms}ms`);\nconsole.log('Summary:', batch.summary); // { allow: 2, challenge: 0, deny: 1 }"
          },
          {
            "lang": "Go",
            "label": "Go",
            "source": "package main\n\nimport (\n    \"bytes\"\n    \"fmt\"\n    \"io\"\n    \"net/http\"\n)\n\nfunc main() {\n    url := \"https://api.emailscore.io/v1/email/bulk\"\n    payload := []byte(`{\"emails\": [\"sarah.jenkins@gmail.com\", \"alex@stripe.com\", \"bot@10minutemail.com\"]}`)\n\n    req, err := http.NewRequest(\"POST\", url, bytes.NewBuffer(payload))\n    if err != nil {\n        panic(err)\n    }\n\n    req.Header.Set(\"Authorization\", \"Bearer YOUR_API_KEY\")\n    req.Header.Set(\"Content-Type\", \"application/json\")\n    req.Header.Set(\"Accept-Encoding\", \"gzip\")\n\n    client := &http.Client{}\n    resp, err := client.Do(req)\n    if err != nil {\n        panic(err)\n    }\n    defer resp.Body.Close()\n\n    body, _ := io.ReadAll(resp.Body)\n    fmt.Println(string(body))\n}"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.emailscore.io/v1/email/bulk\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_POST, true);\ncurl_setopt($ch, CURLOPT_ENCODING, \"gzip\");\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    'Authorization: Bearer YOUR_API_KEY',\n    'Content-Type: application/json',\n    'Accept-Encoding: gzip'\n]);\ncurl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([\n    'emails' => [\n        'sarah.jenkins@gmail.com',\n        'alex@stripe.com',\n        'bot@10minutemail.com'\n    ]\n]));\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\n$batch = json_decode($response, true);\necho \"Verified \" . $batch['processed'] . \"/\" . $batch['total'] . \" in \" . $batch['evaluation_time_ms'] . \"ms\\n\";"
          },
          {
            "lang": "Rust",
            "label": "Rust",
            "source": "use reqwest::header::{ACCEPT_ENCODING, AUTHORIZATION, CONTENT_TYPE};\nuse serde_json::{json, Value};\n\n#[tokio::main]\nasync fn main() -> Result<(), Box<dyn std::error::Error>> {\n    let client = reqwest::Client::new();\n    let res = client\n        .post(\"https://api.emailscore.io/v1/email/bulk\")\n        .header(AUTHORIZATION, \"Bearer YOUR_API_KEY\")\n        .header(CONTENT_TYPE, \"application/json\")\n        .header(ACCEPT_ENCODING, \"gzip\")\n        .json(&json!({\n            \"emails\": [\n                \"sarah.jenkins@gmail.com\",\n                \"alex@stripe.com\",\n                \"bot@10minutemail.com\"\n            ]\n        }))\n        .send()\n        .await?;\n\n    let batch: Value = res.json().await?;\n    println!(\"Processed: {}/{}\", batch[\"processed\"], batch[\"total\"]);\n    println!(\"Summary: {}\", batch[\"summary\"]);\n    Ok(())\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "Batch completed successfully. Returns summary statistics and per-address screening results.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "total": {
                      "type": "integer",
                      "description": "Total number of emails received in the batch."
                    },
                    "processed": {
                      "type": "integer",
                      "description": "Number of emails successfully evaluated."
                    },
                    "evaluation_time_ms": {
                      "type": "number",
                      "description": "Total server-side processing duration in milliseconds."
                    },
                    "summary": {
                      "type": "object",
                      "description": "Aggregate classification counts across the batch.",
                      "properties": {
                        "allow": {
                          "type": "integer",
                          "description": "Total high-confidence legitimate emails."
                        },
                        "challenge": {
                          "type": "integer",
                          "description": "Total moderate-risk / role-based emails."
                        },
                        "deny": {
                          "type": "integer",
                          "description": "Total invalid, disposable, or fraudulent emails."
                        }
                      }
                    },
                    "results": {
                      "type": "array",
                      "description": "Per-email evaluation records.",
                      "items": {
                        "type": "object",
                        "properties": {
                          "email": {
                            "type": "string",
                            "description": "Original email evaluated."
                          },
                          "score": {
                            "type": "integer",
                            "description": "Quality score from 0 to 100."
                          },
                          "decision": {
                            "type": "string",
                            "enum": [
                              "allow",
                              "challenge",
                              "deny"
                            ],
                            "description": "Actionable decision."
                          },
                          "risk_level": {
                            "type": "string",
                            "enum": [
                              "low",
                              "medium",
                              "high",
                              "critical"
                            ],
                            "description": "Risk category."
                          },
                          "account_type": {
                            "type": "string",
                            "enum": [
                              "business",
                              "consumer_free",
                              "education",
                              "government",
                              "disposable"
                            ],
                            "description": "Organization category."
                          },
                          "is_business_email": {
                            "type": "boolean",
                            "description": "True if domain belongs to a commercial enterprise."
                          },
                          "is_disposable": {
                            "type": "boolean",
                            "description": "True if temporary/burner email provider."
                          },
                          "did_you_mean": {
                            "type": "string",
                            "nullable": true,
                            "description": "Typo suggestion if domain was mistyped, else null."
                          },
                          "fingerprint": {
                            "type": "string",
                            "description": "SHA-256 canonical identity hash."
                          },
                          "flags": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            },
                            "description": "Sanitized public security flags."
                          },
                          "recommendation": {
                            "type": "string",
                            "description": "Standardized gatekeeper policy recommendation."
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "total": 3,
                  "processed": 3,
                  "evaluation_time_ms": 1.42,
                  "summary": {
                    "allow": 2,
                    "challenge": 0,
                    "deny": 1
                  },
                  "results": [
                    {
                      "email": "sarah.jenkins@gmail.com",
                      "score": 92,
                      "decision": "allow",
                      "risk_level": "low",
                      "account_type": "consumer_free",
                      "is_business_email": false,
                      "is_disposable": false,
                      "did_you_mean": null,
                      "fingerprint": "8f462664790604f97eab4b104d580d8f824c643038b600a96115bf4014194071",
                      "flags": [],
                      "recommendation": "Allow signup: high confidence legitimate user."
                    },
                    {
                      "email": "alex@stripe.com",
                      "score": 98,
                      "decision": "allow",
                      "risk_level": "low",
                      "account_type": "business",
                      "is_business_email": true,
                      "is_disposable": false,
                      "did_you_mean": null,
                      "fingerprint": "207a9dc3e6aa00898ec0ffbeec946e382cc094bc028f0ee0434407b46618e4bc",
                      "flags": [],
                      "recommendation": "Allow signup: high confidence legitimate user."
                    },
                    {
                      "email": "bot@10minutemail.com",
                      "score": 0,
                      "decision": "deny",
                      "risk_level": "critical",
                      "account_type": "disposable",
                      "is_business_email": false,
                      "is_disposable": true,
                      "did_you_mean": null,
                      "fingerprint": "e57ff311c15b13e90b8f056d3cff4c980387b32a265691079d3be4737d26bbad",
                      "flags": [
                        "DISPOSABLE_DOMAIN"
                      ],
                      "recommendation": "Deny signup: disposable or temporary email addresses are not accepted."
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Emails array cannot be empty or invalid request body.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Batch validation error message."
                    }
                  }
                },
                "example": {
                  "error": "Emails array cannot be empty"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Authentication failure reason."
                    }
                  }
                },
                "example": {
                  "error": "Invalid or revoked API key"
                }
              }
            }
          },
          "429": {
            "description": "Two causes. `rate_limited`: more requests per second than your plan allows. The limit applies to your whole account, across all its API keys; the response carries `Retry-After` (seconds) and `X-Request-Rate-Limit`, and the request uses no credits. Quota: a free Developer allowance is used up with no credit pack balance (paid plans are never blocked by quota; checks past the allowance are billed at the plan's rate).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "`rate_limited`, or a message describing the exhausted allowance."
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable explanation, including when to retry."
                    },
                    "requests_per_second": {
                      "type": "integer",
                      "description": "Your plan's request rate (present when `error` is `rate_limited`)."
                    }
                  }
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Request rate limit reached: 25 requests per second. Retry after 1 second. Bulk endpoints check up to 10000 items in one request.",
                  "requests_per_second": 25
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "emails": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "required": true,
                    "example": [
                      "sarah.jenkins@gmail.com",
                      "alex@stripe.com",
                      "bot@10minutemail.com"
                    ],
                    "description": "Array of email addresses to clean and score (up to 10,000 per request)."
                  },
                  "format": {
                    "type": "string",
                    "required": false,
                    "example": "compact",
                    "description": "Format selector (batch always outputs compact result rows)."
                  },
                  "fields": {
                    "type": "string",
                    "required": false,
                    "example": "email,score,decision,fingerprint",
                    "description": "Optional field mask."
                  }
                }
              },
              "example": {
                "emails": [
                  "sarah.jenkins@gmail.com",
                  "alex@stripe.com",
                  "bot@10minutemail.com"
                ]
              }
            }
          }
        }
      }
    },
    "/v1/domain": {
      "post": {
        "summary": "Score a domain on its own, without an email address",
        "description": "Score a domain by itself: registration age, dead or parked status, disposable providers,\nmail DNS (MX, SPF, DMARC), random-looking names and brand look-alikes, TLD tier, and typo detection.\nReturns a risk score, decision recommendation, and the domain and DNS facts behind it.\n\n`/v1/email` runs this same domain check on the domain part of every address and embeds the\nresult as `domain_verdict`, so the two endpoints never disagree about a domain.\n\n`evidence` is `complete` when DNS was looked up, or `partial` when it was not; with `partial`,\nmail facts (MX, SPF, DMARC) are unknown rather than absent. Uses 1 credit per domain check.\n\nFlags:\n- `TYPO_DOMAIN_SUGGESTION`, `DOMAIN_TYPO_SUSPECTED`: looks like a misspelling of a known provider; see `did_you_mean`.\n- `ZERO_DAY_DOMAIN`: registered 30 days ago or less.\n- `VERY_YOUNG_DOMAIN`: registered 31 to 89 days ago.\n- `DISPOSABLE_DOMAIN`: temporary or throwaway inbox provider.\n- `DEAD_DOMAIN`: does not resolve (NXDOMAIN), abandoned, or dropped.\n- `PARKED_DOMAIN`: parked or holding page.\n- `SUSPICIOUS_TLD`: TLD with a high abuse rate.\n- `SUSPICIOUS_DOMAIN_PATTERN`: random-looking name, brand look-alike, or other name-pattern penalty.\n- `NO_MX_RECORDS`: DNS answered and the domain has no mail servers.\n- `DNS_LOOKUP_INCOMPLETE`: the DNS lookup did not finish; mail facts are unknown, not missing.\n- `NULL_MX_RECORD`: publishes a null MX (RFC 7505), declaring it accepts no mail.\n- `BOGON_MX_RECORD`: MX points to a private or reserved address.\n- `NO_MX_A_RECORD_ONLY`: no MX; mail would fall back to the A record.\n- `GENERIC_HOSTING_PROVIDER`: unrecognized domain without the MX plus SPF or DMARC setup of a maintained organization.\n- `UNESTABLISHED_DOMAIN`: nothing on record establishes the domain (no registration history or reputation), and no more specific flag explains the held verdict.",
        "operationId": "domain_single",
        "tags": [
          "Core Verification"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "domain",
            "in": "query",
            "required": false,
            "description": "Domain to evaluate via GET query parameter (alternative to POST JSON body).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "cURL",
            "source": "curl -sS -X POST \"https://api.emailscore.io/v1/domain\" \\\n  -H \"Authorization: Bearer YOUR_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"domain\": \"acme.com\"}'"
          },
          {
            "lang": "Ruby",
            "label": "Ruby",
            "source": "require 'net/http'\nrequire 'uri'\nrequire 'json'\n\nuri = URI('https://api.emailscore.io/v1/domain')\nhttp = Net::HTTP.new(uri.host, uri.port)\nhttp.use_ssl = true\n\nreq = Net::HTTP::Post.new(uri.path, {\n  'Authorization' => 'Bearer YOUR_API_KEY',\n  'Content-Type' => 'application/json'\n})\nreq.body = { domain: 'acme.com' }.to_json\n\nres = http.request(req)\ndata = JSON.parse(res.body)\n\nputs \"Score: #{data['score']}/100 | Decision: #{data['decision'].upcase}\"\nputs \"Evidence: #{data['evidence']} | Flags: #{data['flags'].join(', ')}\"\nputs \"Recommendation: #{data['recommendation']}\""
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import requests\n\nurl = \"https://api.emailscore.io/v1/domain\"\nheaders = {\n    \"Authorization\": \"Bearer YOUR_API_KEY\",\n    \"Content-Type\": \"application/json\",\n}\npayload = {\"domain\": \"acme.com\"}\n\nresponse = requests.post(url, json=payload, headers=headers)\ndata = response.json()\n\nprint(f\"Domain: {data['domain']}\")\nprint(f\"Score: {data['score']}/100 -> Decision: {data['decision'].upper()}\")\nprint(f\"Evidence: {data['evidence']} | Flags: {data['flags']}\")\nprint(f\"Recommendation: {data['recommendation']}\")"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "// Domain Check\nconst response = await fetch('https://api.emailscore.io/v1/domain', {\n  method: 'POST',\n  headers: {\n    'Authorization': 'Bearer YOUR_API_KEY',\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    domain: 'acme.com'\n  }),\n});\n\nconst result = await response.json();\nconsole.log(`Score: ${result.score}/100 | Decision: ${result.decision}`);\nconsole.log('Evidence:', result.evidence, '| Flags:', result.flags);"
          },
          {
            "lang": "Go",
            "label": "Go",
            "source": "package main\n\nimport (\n    \"bytes\"\n    \"fmt\"\n    \"io\"\n    \"net/http\"\n)\n\nfunc main() {\n    url := \"https://api.emailscore.io/v1/domain\"\n    payload := []byte(`{\"domain\": \"acme.com\"}`)\n\n    req, err := http.NewRequest(\"POST\", url, bytes.NewBuffer(payload))\n    if err != nil {\n        panic(err)\n    }\n\n    req.Header.Set(\"Authorization\", \"Bearer YOUR_API_KEY\")\n    req.Header.Set(\"Content-Type\", \"application/json\")\n\n    client := &http.Client{}\n    resp, err := client.Do(req)\n    if err != nil {\n        panic(err)\n    }\n    defer resp.Body.Close()\n\n    body, _ := io.ReadAll(resp.Body)\n    fmt.Println(string(body))\n}"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.emailscore.io/v1/domain\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_POST, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    'Authorization: Bearer YOUR_API_KEY',\n    'Content-Type: application/json'\n]);\ncurl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([\n    'domain' => 'acme.com'\n]));\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\n$result = json_decode($response, true);\necho \"Score: \" . $result['score'] . \"/100 | Decision: \" . strtoupper($result['decision']) . \"\\n\";\necho \"Evidence: \" . $result['evidence'] . \"\\n\";"
          },
          {
            "lang": "Rust",
            "label": "Rust",
            "source": "use reqwest::header::{AUTHORIZATION, CONTENT_TYPE};\nuse serde_json::{json, Value};\n\n#[tokio::main]\nasync fn main() -> Result<(), Box<dyn std::error::Error>> {\n    let client = reqwest::Client::new();\n    let res = client\n        .post(\"https://api.emailscore.io/v1/domain\")\n        .header(AUTHORIZATION, \"Bearer YOUR_API_KEY\")\n        .header(CONTENT_TYPE, \"application/json\")\n        .json(&json!({ \"domain\": \"acme.com\" }))\n        .send()\n        .await?;\n\n    let json: Value = res.json().await?;\n    println!(\"Score: {} | Decision: {}\", json[\"score\"], json[\"decision\"]);\n    println!(\"Evidence: {} | Flags: {}\", json[\"evidence\"], json[\"flags\"]);\n    Ok(())\n}"
          }
        ],
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "cURL",
            "source": "curl -sS -X POST \"https://api.emailscore.io/v1/domain\" \\\n  -H \"Authorization: Bearer YOUR_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"domain\": \"acme.com\"}'"
          },
          {
            "lang": "Ruby",
            "label": "Ruby",
            "source": "require 'net/http'\nrequire 'uri'\nrequire 'json'\n\nuri = URI('https://api.emailscore.io/v1/domain')\nhttp = Net::HTTP.new(uri.host, uri.port)\nhttp.use_ssl = true\n\nreq = Net::HTTP::Post.new(uri.path, {\n  'Authorization' => 'Bearer YOUR_API_KEY',\n  'Content-Type' => 'application/json'\n})\nreq.body = { domain: 'acme.com' }.to_json\n\nres = http.request(req)\ndata = JSON.parse(res.body)\n\nputs \"Score: #{data['score']}/100 | Decision: #{data['decision'].upcase}\"\nputs \"Evidence: #{data['evidence']} | Flags: #{data['flags'].join(', ')}\"\nputs \"Recommendation: #{data['recommendation']}\""
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import requests\n\nurl = \"https://api.emailscore.io/v1/domain\"\nheaders = {\n    \"Authorization\": \"Bearer YOUR_API_KEY\",\n    \"Content-Type\": \"application/json\",\n}\npayload = {\"domain\": \"acme.com\"}\n\nresponse = requests.post(url, json=payload, headers=headers)\ndata = response.json()\n\nprint(f\"Domain: {data['domain']}\")\nprint(f\"Score: {data['score']}/100 -> Decision: {data['decision'].upper()}\")\nprint(f\"Evidence: {data['evidence']} | Flags: {data['flags']}\")\nprint(f\"Recommendation: {data['recommendation']}\")"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "// Domain Check\nconst response = await fetch('https://api.emailscore.io/v1/domain', {\n  method: 'POST',\n  headers: {\n    'Authorization': 'Bearer YOUR_API_KEY',\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    domain: 'acme.com'\n  }),\n});\n\nconst result = await response.json();\nconsole.log(`Score: ${result.score}/100 | Decision: ${result.decision}`);\nconsole.log('Evidence:', result.evidence, '| Flags:', result.flags);"
          },
          {
            "lang": "Go",
            "label": "Go",
            "source": "package main\n\nimport (\n    \"bytes\"\n    \"fmt\"\n    \"io\"\n    \"net/http\"\n)\n\nfunc main() {\n    url := \"https://api.emailscore.io/v1/domain\"\n    payload := []byte(`{\"domain\": \"acme.com\"}`)\n\n    req, err := http.NewRequest(\"POST\", url, bytes.NewBuffer(payload))\n    if err != nil {\n        panic(err)\n    }\n\n    req.Header.Set(\"Authorization\", \"Bearer YOUR_API_KEY\")\n    req.Header.Set(\"Content-Type\", \"application/json\")\n\n    client := &http.Client{}\n    resp, err := client.Do(req)\n    if err != nil {\n        panic(err)\n    }\n    defer resp.Body.Close()\n\n    body, _ := io.ReadAll(resp.Body)\n    fmt.Println(string(body))\n}"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.emailscore.io/v1/domain\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_POST, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    'Authorization: Bearer YOUR_API_KEY',\n    'Content-Type: application/json'\n]);\ncurl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([\n    'domain' => 'acme.com'\n]));\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\n$result = json_decode($response, true);\necho \"Score: \" . $result['score'] . \"/100 | Decision: \" . strtoupper($result['decision']) . \"\\n\";\necho \"Evidence: \" . $result['evidence'] . \"\\n\";"
          },
          {
            "lang": "Rust",
            "label": "Rust",
            "source": "use reqwest::header::{AUTHORIZATION, CONTENT_TYPE};\nuse serde_json::{json, Value};\n\n#[tokio::main]\nasync fn main() -> Result<(), Box<dyn std::error::Error>> {\n    let client = reqwest::Client::new();\n    let res = client\n        .post(\"https://api.emailscore.io/v1/domain\")\n        .header(AUTHORIZATION, \"Bearer YOUR_API_KEY\")\n        .header(CONTENT_TYPE, \"application/json\")\n        .json(&json!({ \"domain\": \"acme.com\" }))\n        .send()\n        .await?;\n\n    let json: Value = res.json().await?;\n    println!(\"Score: {} | Decision: {}\", json[\"score\"], json[\"decision\"]);\n    println!(\"Evidence: {} | Flags: {}\", json[\"evidence\"], json[\"flags\"]);\n    Ok(())\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful evaluation. Returns the domain verdict with its domain and DNS facts.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "domain": {
                      "type": "string",
                      "description": "Domain evaluated."
                    },
                    "score": {
                      "type": "integer",
                      "description": "Domain risk score from 0 (dead, disposable, or unusable for mail) to 100 (established domain with working mail)."
                    },
                    "decision": {
                      "type": "string",
                      "enum": [
                        "allow",
                        "challenge",
                        "deny"
                      ],
                      "description": "Risk-based policy recommendation: `allow`, `challenge`, or `deny`. It describes the domain only, not any mailbox on it."
                    },
                    "risk_level": {
                      "type": "string",
                      "enum": [
                        "low",
                        "medium",
                        "high",
                        "critical"
                      ],
                      "description": "Categorical risk assessment."
                    },
                    "recommendation": {
                      "type": "string",
                      "description": "Short explanation of the decision."
                    },
                    "flags": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Domain risk flags (listed in the endpoint description). Empty array for a clean domain."
                    },
                    "evidence": {
                      "type": "string",
                      "enum": [
                        "complete",
                        "partial"
                      ],
                      "description": "`complete` when DNS was looked up. `partial` when it was not, so MX, SPF, and DMARC are unknown."
                    },
                    "did_you_mean": {
                      "type": "string",
                      "nullable": true,
                      "description": "Suggested domain when the input looks like a typo of a known provider (e.g. `gmail.com` for `gmial.com`), else null."
                    },
                    "evaluation_time_ms": {
                      "type": "number",
                      "description": "Server-side evaluation time in milliseconds for this request; not an end-to-end API latency guarantee."
                    },
                    "domain_quality": {
                      "type": "object",
                      "description": "Domain reputation, registration age, and status.",
                      "properties": {
                        "score": {
                          "type": "integer",
                          "description": "Domain quality score (0-100)."
                        },
                        "domain": {
                          "type": "string",
                          "description": "Domain evaluated."
                        },
                        "registered_date": {
                          "type": "string",
                          "nullable": true,
                          "description": "Original domain registration date (YYYY-MM-DD)."
                        },
                        "registered_at": {
                          "type": "integer",
                          "nullable": true,
                          "description": "Unix epoch timestamp of registration."
                        },
                        "age_days": {
                          "type": "integer",
                          "nullable": true,
                          "description": "Domain age in days, calculated at request time."
                        },
                        "provider_type": {
                          "type": "string",
                          "enum": [
                            "disposable",
                            "public_free",
                            "custom_corporate",
                            "generic_hosted"
                          ],
                          "description": "Domain infrastructure type."
                        },
                        "tld_tier": {
                          "type": "string",
                          "enum": [
                            "premium",
                            "standard",
                            "suspicious"
                          ],
                          "description": "TLD abuse reputation tier."
                        },
                        "is_dead": {
                          "type": "boolean",
                          "description": "True if domain is NXDOMAIN, abandoned, or dropped."
                        },
                        "is_parked": {
                          "type": "boolean",
                          "description": "True if domain is parked or a holding page."
                        },
                        "length": {
                          "type": "integer",
                          "description": "Character length of the domain name."
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "active",
                            "dead",
                            "parked",
                            "no_mx"
                          ],
                          "description": "Domain status."
                        }
                      }
                    },
                    "dns": {
                      "type": "object",
                      "description": "Mail DNS for the domain. Unknown when `evidence` is `partial`.",
                      "properties": {
                        "has_mx": {
                          "type": "boolean",
                          "description": "True if domain has valid MX or fallback mail exchangers."
                        },
                        "mx_records": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "description": "List of resolved mail exchanger hosts."
                        },
                        "vendor": {
                          "type": "string",
                          "description": "Detected email infrastructure vendor (e.g. Google Workspace, Microsoft 365)."
                        },
                        "has_spf": {
                          "type": "boolean",
                          "description": "True if SPF records are configured."
                        },
                        "has_dmarc": {
                          "type": "boolean",
                          "description": "True if DMARC policy is published."
                        },
                        "resolution_status": {
                          "type": "string",
                          "description": "DNS resolution status code."
                        }
                      }
                    }
                  }
                },
                "example": {
                  "domain": "acme.com",
                  "score": 91,
                  "decision": "allow",
                  "risk_level": "low",
                  "recommendation": "Allow: established domain with working mail.",
                  "flags": [],
                  "evidence": "complete",
                  "did_you_mean": null,
                  "evaluation_time_ms": 0.08,
                  "domain_quality": {
                    "score": 85,
                    "domain": "acme.com",
                    "registered_date": "1997-09-15",
                    "registered_at": 874281600,
                    "age_days": 10600,
                    "provider_type": "custom_corporate",
                    "tld_tier": "premium",
                    "is_dead": false,
                    "is_parked": false,
                    "length": 8,
                    "status": "active"
                  },
                  "dns": {
                    "has_mx": true,
                    "mx_records": [
                      "mx1.acme.com"
                    ],
                    "vendor": "Google Workspace",
                    "has_spf": true,
                    "has_dmarc": true,
                    "resolution_status": "preloaded_ledger"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Malformed request, or missing or invalid domain.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Reason the evaluation failed."
                    }
                  }
                },
                "example": {
                  "error": "Domain is missing or invalid: expected a hostname such as example.com"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Authentication error message."
                    }
                  }
                },
                "example": {
                  "error": "Invalid or revoked API key"
                }
              }
            }
          },
          "429": {
            "description": "Two causes. `rate_limited`: more requests per second than your plan allows. The limit applies to your whole account, across all its API keys; the response carries `Retry-After` (seconds) and `X-Request-Rate-Limit`, and the request uses no credits. Quota: a free Developer allowance is used up with no credit pack balance (paid plans are never blocked by quota; checks past the allowance are billed at the plan's rate).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "`rate_limited`, or a message describing the exhausted allowance."
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable explanation, including when to retry."
                    },
                    "requests_per_second": {
                      "type": "integer",
                      "description": "Your plan's request rate (present when `error` is `rate_limited`)."
                    }
                  }
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Request rate limit reached: 25 requests per second. Retry after 1 second. Bulk endpoints check up to 10000 items in one request.",
                  "requests_per_second": 25
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "domain": {
                    "type": "string",
                    "required": true,
                    "example": "acme.com",
                    "description": "The domain name to score, without a local part or `@`."
                  }
                }
              },
              "example": {
                "domain": "acme.com"
              }
            }
          }
        }
      }
    },
    "/v1/domain/bulk": {
      "post": {
        "summary": "Score a batch of domains",
        "description": "Score up to 10,000 domains in one request. Each result is produced by the same domain check as\n`/v1/domain`, so a domain's bulk result always equals its single `/v1/domain` result without\n`domain_quality`, `dns`, and `evaluation_time_ms`.\n\nSend `{\"domains\": [...]}` or a raw JSON array of strings. Results come back in the order submitted.\nValid domains are returned normalized (trimmed, lowercased, trailing dot removed); an invalid entry\nis returned as submitted (trimmed) with the `INVALID_FORMAT` flag.\n\nUses 1 credit per submitted domain, invalid entries included. Guest trial tokens (`es_temp_...`)\ncannot use bulk and receive 403 `registration_required`.\n\n`evidence` is `complete` when DNS was looked up, or `partial` when it was not; with `partial`,\nmail facts (MX, SPF, DMARC) are unknown rather than absent.\n\nFlags:\n- `INVALID_FORMAT`: the entry is not a valid domain name.\n- `TYPO_DOMAIN_SUGGESTION`, `DOMAIN_TYPO_SUSPECTED`: looks like a misspelling of a known provider; see `did_you_mean`.\n- `ZERO_DAY_DOMAIN`: registered 30 days ago or less.\n- `VERY_YOUNG_DOMAIN`: registered 31 to 89 days ago.\n- `DISPOSABLE_DOMAIN`: temporary or throwaway inbox provider.\n- `DEAD_DOMAIN`: does not resolve (NXDOMAIN), abandoned, or dropped.\n- `PARKED_DOMAIN`: parked or holding page.\n- `SUSPICIOUS_TLD`: TLD with a high abuse rate.\n- `SUSPICIOUS_DOMAIN_PATTERN`: random-looking name, brand look-alike, or other name-pattern penalty.\n- `NO_MX_RECORDS`: DNS answered and the domain has no mail servers.\n- `DNS_LOOKUP_INCOMPLETE`: the DNS lookup did not finish; mail facts are unknown, not missing.\n- `NULL_MX_RECORD`: publishes a null MX (RFC 7505), declaring it accepts no mail.\n- `BOGON_MX_RECORD`: MX points to a private or reserved address.\n- `NO_MX_A_RECORD_ONLY`: no MX; mail would fall back to the A record.\n- `GENERIC_HOSTING_PROVIDER`: unrecognized domain without the MX plus SPF or DMARC setup of a maintained organization.\n- `UNESTABLISHED_DOMAIN`: nothing on record establishes the domain (no registration history or reputation), and no more specific flag explains the held verdict.",
        "operationId": "domain_bulk",
        "tags": [
          "Core Verification"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [],
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "cURL",
            "source": "curl -sS -X POST \"https://api.emailscore.io/v1/domain/bulk\" \\\n  -H \"Authorization: Bearer YOUR_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Accept-Encoding: gzip\" \\\n  -d '{\"domains\": [\"google.com\", \"gmial.com\", \"not a domain\"]}'"
          },
          {
            "lang": "Ruby",
            "label": "Ruby",
            "source": "require 'net/http'\nrequire 'uri'\nrequire 'json'\n\nuri = URI('https://api.emailscore.io/v1/domain/bulk')\nhttp = Net::HTTP.new(uri.host, uri.port)\nhttp.use_ssl = true\n\nreq = Net::HTTP::Post.new(uri.path, {\n  'Authorization' => 'Bearer YOUR_API_KEY',\n  'Content-Type' => 'application/json',\n  'Accept-Encoding' => 'gzip'\n})\nreq.body = {\n  domains: [\n    'google.com',\n    'gmial.com',\n    'not a domain'\n  ]\n}.to_json\n\nres = http.request(req)\nbatch = JSON.parse(res.body)\n\nputs \"Scored #{batch['processed']}/#{batch['total']} in #{batch['evaluation_time_ms']}ms\"\nputs \"Summary: Allow=#{batch.dig('summary', 'allow')}, Deny=#{batch.dig('summary', 'deny')}\"\n\nbatch['results'].each do |item|\n  puts \"  [#{item['decision'].upcase}] #{item['domain']} -> Score: #{item['score']} #{item['flags'].join(',')}\"\nend"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import requests\n\nurl = \"https://api.emailscore.io/v1/domain/bulk\"\nheaders = {\n    \"Authorization\": \"Bearer YOUR_API_KEY\",\n    \"Content-Type\": \"application/json\",\n    \"Accept-Encoding\": \"gzip\",\n}\npayload = {\n    \"domains\": [\n        \"google.com\",\n        \"gmial.com\",\n        \"not a domain\",\n    ]\n}\n\nresponse = requests.post(url, json=payload, headers=headers)\ndata = response.json()\n\nprint(f\"Total: {data['total']} | Evaluation Time: {data['evaluation_time_ms']}ms\")\nprint(f\"Summary: Allow={data['summary']['allow']}, Deny={data['summary']['deny']}\")\nfor item in data['results']:\n    print(f\" - {item['domain']}: {item['score']} ({item['decision']}) {item['flags']}\")"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "// Bulk / Batch Domain Check (up to 10,000 domains per request)\nconst response = await fetch('https://api.emailscore.io/v1/domain/bulk', {\n  method: 'POST',\n  headers: {\n    'Authorization': 'Bearer YOUR_API_KEY',\n    'Content-Type': 'application/json',\n    'Accept-Encoding': 'gzip',\n  },\n  body: JSON.stringify({\n    domains: [\n      'google.com',\n      'gmial.com',\n      'not a domain',\n    ]\n  }),\n});\n\nconst batch = await response.json();\nconsole.log(`Scored ${batch.processed}/${batch.total} in ${batch.evaluation_time_ms}ms`);\nconsole.log('Summary:', batch.summary); // { allow: 1, challenge: 0, deny: 2 }"
          },
          {
            "lang": "Go",
            "label": "Go",
            "source": "package main\n\nimport (\n    \"bytes\"\n    \"fmt\"\n    \"io\"\n    \"net/http\"\n)\n\nfunc main() {\n    url := \"https://api.emailscore.io/v1/domain/bulk\"\n    payload := []byte(`{\"domains\": [\"google.com\", \"gmial.com\", \"not a domain\"]}`)\n\n    req, err := http.NewRequest(\"POST\", url, bytes.NewBuffer(payload))\n    if err != nil {\n        panic(err)\n    }\n\n    req.Header.Set(\"Authorization\", \"Bearer YOUR_API_KEY\")\n    req.Header.Set(\"Content-Type\", \"application/json\")\n    req.Header.Set(\"Accept-Encoding\", \"gzip\")\n\n    client := &http.Client{}\n    resp, err := client.Do(req)\n    if err != nil {\n        panic(err)\n    }\n    defer resp.Body.Close()\n\n    body, _ := io.ReadAll(resp.Body)\n    fmt.Println(string(body))\n}"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.emailscore.io/v1/domain/bulk\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_POST, true);\ncurl_setopt($ch, CURLOPT_ENCODING, \"gzip\");\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    'Authorization: Bearer YOUR_API_KEY',\n    'Content-Type: application/json',\n    'Accept-Encoding: gzip'\n]);\ncurl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([\n    'domains' => [\n        'google.com',\n        'gmial.com',\n        'not a domain'\n    ]\n]));\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\n$batch = json_decode($response, true);\necho \"Scored \" . $batch['processed'] . \"/\" . $batch['total'] . \" in \" . $batch['evaluation_time_ms'] . \"ms\\n\";"
          },
          {
            "lang": "Rust",
            "label": "Rust",
            "source": "use reqwest::header::{ACCEPT_ENCODING, AUTHORIZATION, CONTENT_TYPE};\nuse serde_json::{json, Value};\n\n#[tokio::main]\nasync fn main() -> Result<(), Box<dyn std::error::Error>> {\n    let client = reqwest::Client::new();\n    let res = client\n        .post(\"https://api.emailscore.io/v1/domain/bulk\")\n        .header(AUTHORIZATION, \"Bearer YOUR_API_KEY\")\n        .header(CONTENT_TYPE, \"application/json\")\n        .header(ACCEPT_ENCODING, \"gzip\")\n        .json(&json!({\n            \"domains\": [\n                \"google.com\",\n                \"gmial.com\",\n                \"not a domain\"\n            ]\n        }))\n        .send()\n        .await?;\n\n    let batch: Value = res.json().await?;\n    println!(\"Processed: {}/{}\", batch[\"processed\"], batch[\"total\"]);\n    println!(\"Summary: {}\", batch[\"summary\"]);\n    Ok(())\n}"
          }
        ],
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "cURL",
            "source": "curl -sS -X POST \"https://api.emailscore.io/v1/domain/bulk\" \\\n  -H \"Authorization: Bearer YOUR_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Accept-Encoding: gzip\" \\\n  -d '{\"domains\": [\"google.com\", \"gmial.com\", \"not a domain\"]}'"
          },
          {
            "lang": "Ruby",
            "label": "Ruby",
            "source": "require 'net/http'\nrequire 'uri'\nrequire 'json'\n\nuri = URI('https://api.emailscore.io/v1/domain/bulk')\nhttp = Net::HTTP.new(uri.host, uri.port)\nhttp.use_ssl = true\n\nreq = Net::HTTP::Post.new(uri.path, {\n  'Authorization' => 'Bearer YOUR_API_KEY',\n  'Content-Type' => 'application/json',\n  'Accept-Encoding' => 'gzip'\n})\nreq.body = {\n  domains: [\n    'google.com',\n    'gmial.com',\n    'not a domain'\n  ]\n}.to_json\n\nres = http.request(req)\nbatch = JSON.parse(res.body)\n\nputs \"Scored #{batch['processed']}/#{batch['total']} in #{batch['evaluation_time_ms']}ms\"\nputs \"Summary: Allow=#{batch.dig('summary', 'allow')}, Deny=#{batch.dig('summary', 'deny')}\"\n\nbatch['results'].each do |item|\n  puts \"  [#{item['decision'].upcase}] #{item['domain']} -> Score: #{item['score']} #{item['flags'].join(',')}\"\nend"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import requests\n\nurl = \"https://api.emailscore.io/v1/domain/bulk\"\nheaders = {\n    \"Authorization\": \"Bearer YOUR_API_KEY\",\n    \"Content-Type\": \"application/json\",\n    \"Accept-Encoding\": \"gzip\",\n}\npayload = {\n    \"domains\": [\n        \"google.com\",\n        \"gmial.com\",\n        \"not a domain\",\n    ]\n}\n\nresponse = requests.post(url, json=payload, headers=headers)\ndata = response.json()\n\nprint(f\"Total: {data['total']} | Evaluation Time: {data['evaluation_time_ms']}ms\")\nprint(f\"Summary: Allow={data['summary']['allow']}, Deny={data['summary']['deny']}\")\nfor item in data['results']:\n    print(f\" - {item['domain']}: {item['score']} ({item['decision']}) {item['flags']}\")"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "// Bulk / Batch Domain Check (up to 10,000 domains per request)\nconst response = await fetch('https://api.emailscore.io/v1/domain/bulk', {\n  method: 'POST',\n  headers: {\n    'Authorization': 'Bearer YOUR_API_KEY',\n    'Content-Type': 'application/json',\n    'Accept-Encoding': 'gzip',\n  },\n  body: JSON.stringify({\n    domains: [\n      'google.com',\n      'gmial.com',\n      'not a domain',\n    ]\n  }),\n});\n\nconst batch = await response.json();\nconsole.log(`Scored ${batch.processed}/${batch.total} in ${batch.evaluation_time_ms}ms`);\nconsole.log('Summary:', batch.summary); // { allow: 1, challenge: 0, deny: 2 }"
          },
          {
            "lang": "Go",
            "label": "Go",
            "source": "package main\n\nimport (\n    \"bytes\"\n    \"fmt\"\n    \"io\"\n    \"net/http\"\n)\n\nfunc main() {\n    url := \"https://api.emailscore.io/v1/domain/bulk\"\n    payload := []byte(`{\"domains\": [\"google.com\", \"gmial.com\", \"not a domain\"]}`)\n\n    req, err := http.NewRequest(\"POST\", url, bytes.NewBuffer(payload))\n    if err != nil {\n        panic(err)\n    }\n\n    req.Header.Set(\"Authorization\", \"Bearer YOUR_API_KEY\")\n    req.Header.Set(\"Content-Type\", \"application/json\")\n    req.Header.Set(\"Accept-Encoding\", \"gzip\")\n\n    client := &http.Client{}\n    resp, err := client.Do(req)\n    if err != nil {\n        panic(err)\n    }\n    defer resp.Body.Close()\n\n    body, _ := io.ReadAll(resp.Body)\n    fmt.Println(string(body))\n}"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.emailscore.io/v1/domain/bulk\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_POST, true);\ncurl_setopt($ch, CURLOPT_ENCODING, \"gzip\");\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    'Authorization: Bearer YOUR_API_KEY',\n    'Content-Type: application/json',\n    'Accept-Encoding: gzip'\n]);\ncurl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([\n    'domains' => [\n        'google.com',\n        'gmial.com',\n        'not a domain'\n    ]\n]));\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\n$batch = json_decode($response, true);\necho \"Scored \" . $batch['processed'] . \"/\" . $batch['total'] . \" in \" . $batch['evaluation_time_ms'] . \"ms\\n\";"
          },
          {
            "lang": "Rust",
            "label": "Rust",
            "source": "use reqwest::header::{ACCEPT_ENCODING, AUTHORIZATION, CONTENT_TYPE};\nuse serde_json::{json, Value};\n\n#[tokio::main]\nasync fn main() -> Result<(), Box<dyn std::error::Error>> {\n    let client = reqwest::Client::new();\n    let res = client\n        .post(\"https://api.emailscore.io/v1/domain/bulk\")\n        .header(AUTHORIZATION, \"Bearer YOUR_API_KEY\")\n        .header(CONTENT_TYPE, \"application/json\")\n        .header(ACCEPT_ENCODING, \"gzip\")\n        .json(&json!({\n            \"domains\": [\n                \"google.com\",\n                \"gmial.com\",\n                \"not a domain\"\n            ]\n        }))\n        .send()\n        .await?;\n\n    let batch: Value = res.json().await?;\n    println!(\"Processed: {}/{}\", batch[\"processed\"], batch[\"total\"]);\n    println!(\"Summary: {}\", batch[\"summary\"]);\n    Ok(())\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "Batch completed. Returns summary counts and one result per submitted domain, in submission order.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "total": {
                      "type": "integer",
                      "description": "Number of domains received in the batch."
                    },
                    "processed": {
                      "type": "integer",
                      "description": "Number of domains evaluated."
                    },
                    "evaluation_time_ms": {
                      "type": "number",
                      "description": "Total server-side processing duration in milliseconds for the batch."
                    },
                    "summary": {
                      "type": "object",
                      "description": "Decision counts across the batch.",
                      "properties": {
                        "allow": {
                          "type": "integer",
                          "description": "Domains with an `allow` decision."
                        },
                        "challenge": {
                          "type": "integer",
                          "description": "Domains with a `challenge` decision."
                        },
                        "deny": {
                          "type": "integer",
                          "description": "Domains with a `deny` decision, including invalid entries."
                        }
                      }
                    },
                    "results": {
                      "type": "array",
                      "description": "Per-domain verdicts in submission order. Each equals the `/v1/domain` result for that domain without `domain_quality`, `dns`, and `evaluation_time_ms`.",
                      "items": {
                        "type": "object",
                        "properties": {
                          "domain": {
                            "type": "string",
                            "description": "Normalized domain (trimmed, lowercased, trailing dot removed), or the trimmed input for an invalid entry."
                          },
                          "score": {
                            "type": "integer",
                            "description": "Domain risk score from 0 to 100."
                          },
                          "decision": {
                            "type": "string",
                            "enum": [
                              "allow",
                              "challenge",
                              "deny"
                            ],
                            "description": "Recommendation for the domain: `allow`, `challenge`, or `deny`."
                          },
                          "risk_level": {
                            "type": "string",
                            "enum": [
                              "low",
                              "medium",
                              "high",
                              "critical"
                            ],
                            "description": "Categorical risk assessment."
                          },
                          "recommendation": {
                            "type": "string",
                            "description": "Short explanation of the decision."
                          },
                          "flags": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            },
                            "description": "Domain risk flags (listed in the endpoint description). Empty array for a clean domain."
                          },
                          "evidence": {
                            "type": "string",
                            "enum": [
                              "complete",
                              "partial"
                            ],
                            "description": "`complete` when DNS was looked up. `partial` when it was not, so MX, SPF, and DMARC are unknown."
                          },
                          "did_you_mean": {
                            "type": "string",
                            "nullable": true,
                            "description": "Suggested domain when the input looks like a typo of a known provider, else null."
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "total": 3,
                  "processed": 3,
                  "evaluation_time_ms": 41.7,
                  "summary": {
                    "allow": 1,
                    "challenge": 0,
                    "deny": 2
                  },
                  "results": [
                    {
                      "domain": "google.com",
                      "score": 100,
                      "decision": "allow",
                      "risk_level": "low",
                      "recommendation": "Allow: established domain with working mail.",
                      "flags": [],
                      "evidence": "complete",
                      "did_you_mean": null
                    },
                    {
                      "domain": "gmial.com",
                      "score": 0,
                      "decision": "deny",
                      "risk_level": "critical",
                      "recommendation": "Deny: disposable or temporary email addresses are not accepted.",
                      "flags": [
                        "TYPO_DOMAIN_SUGGESTION",
                        "DOMAIN_TYPO_SUSPECTED",
                        "DISPOSABLE_DOMAIN"
                      ],
                      "evidence": "partial",
                      "did_you_mean": "gmail.com"
                    },
                    {
                      "domain": "not a domain",
                      "score": 0,
                      "decision": "deny",
                      "risk_level": "critical",
                      "recommendation": "Deny: not a valid domain.",
                      "flags": [
                        "INVALID_FORMAT"
                      ],
                      "evidence": "partial",
                      "did_you_mean": null
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Empty `domains` array (`{\"error\": \"Domains array cannot be empty\"}`), invalid request body, or more than 10,000 domains.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Batch validation error message."
                    },
                    "max_batch_size": {
                      "type": "integer",
                      "description": "Maximum domains per request. Present only when the batch is too large."
                    },
                    "received": {
                      "type": "integer",
                      "description": "Number of domains submitted. Present only when the batch is too large."
                    }
                  }
                },
                "example": {
                  "error": "Batch size exceeds maximum limit of 10000 domains per request. Please submit in batches of up to 10000.",
                  "max_batch_size": 10000,
                  "received": 10001
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Authentication failure reason."
                    }
                  }
                },
                "example": {
                  "error": "Invalid or revoked API key"
                }
              }
            }
          },
          "403": {
            "description": "Guest trial token (`es_temp_...`) used on a bulk endpoint. Register for an API key.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Machine-readable reason: `registration_required`."
                    },
                    "message": {
                      "type": "string",
                      "description": "Guidance for obtaining an API key."
                    }
                  }
                },
                "example": {
                  "error": "registration_required"
                }
              }
            }
          },
          "429": {
            "description": "Two causes. `rate_limited`: more requests per second than your plan allows. The limit applies to your whole account, across all its API keys; the response carries `Retry-After` (seconds) and `X-Request-Rate-Limit`, and the request uses no credits. Quota: a free Developer allowance is used up with no credit pack balance (paid plans are never blocked by quota; checks past the allowance are billed at the plan's rate).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "`rate_limited`, or a message describing the exhausted allowance."
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable explanation, including when to retry."
                    },
                    "requests_per_second": {
                      "type": "integer",
                      "description": "Your plan's request rate (present when `error` is `rate_limited`)."
                    }
                  }
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Request rate limit reached: 25 requests per second. Retry after 1 second. Bulk endpoints check up to 10000 items in one request.",
                  "requests_per_second": 25
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "domains": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "required": true,
                    "example": [
                      "google.com",
                      "gmial.com",
                      "not a domain"
                    ],
                    "description": "Array of domains to score (1 to 10,000 per request). A raw JSON array of strings is also accepted as the whole body."
                  }
                }
              },
              "example": {
                "domains": [
                  "google.com",
                  "gmial.com",
                  "not a domain"
                ]
              }
            }
          }
        }
      }
    },
    "/v1/domain/batch": {
      "post": {
        "summary": "Score a batch of domains (Alias)",
        "description": "Score up to 10,000 domains in one request. Each result is produced by the same domain check as\n`/v1/domain`, so a domain's bulk result always equals its single `/v1/domain` result without\n`domain_quality`, `dns`, and `evaluation_time_ms`.\n\nSend `{\"domains\": [...]}` or a raw JSON array of strings. Results come back in the order submitted.\nValid domains are returned normalized (trimmed, lowercased, trailing dot removed); an invalid entry\nis returned as submitted (trimmed) with the `INVALID_FORMAT` flag.\n\nUses 1 credit per submitted domain, invalid entries included. Guest trial tokens (`es_temp_...`)\ncannot use bulk and receive 403 `registration_required`.\n\n`evidence` is `complete` when DNS was looked up, or `partial` when it was not; with `partial`,\nmail facts (MX, SPF, DMARC) are unknown rather than absent.\n\nFlags:\n- `INVALID_FORMAT`: the entry is not a valid domain name.\n- `TYPO_DOMAIN_SUGGESTION`, `DOMAIN_TYPO_SUSPECTED`: looks like a misspelling of a known provider; see `did_you_mean`.\n- `ZERO_DAY_DOMAIN`: registered 30 days ago or less.\n- `VERY_YOUNG_DOMAIN`: registered 31 to 89 days ago.\n- `DISPOSABLE_DOMAIN`: temporary or throwaway inbox provider.\n- `DEAD_DOMAIN`: does not resolve (NXDOMAIN), abandoned, or dropped.\n- `PARKED_DOMAIN`: parked or holding page.\n- `SUSPICIOUS_TLD`: TLD with a high abuse rate.\n- `SUSPICIOUS_DOMAIN_PATTERN`: random-looking name, brand look-alike, or other name-pattern penalty.\n- `NO_MX_RECORDS`: DNS answered and the domain has no mail servers.\n- `DNS_LOOKUP_INCOMPLETE`: the DNS lookup did not finish; mail facts are unknown, not missing.\n- `NULL_MX_RECORD`: publishes a null MX (RFC 7505), declaring it accepts no mail.\n- `BOGON_MX_RECORD`: MX points to a private or reserved address.\n- `NO_MX_A_RECORD_ONLY`: no MX; mail would fall back to the A record.\n- `GENERIC_HOSTING_PROVIDER`: unrecognized domain without the MX plus SPF or DMARC setup of a maintained organization.\n- `UNESTABLISHED_DOMAIN`: nothing on record establishes the domain (no registration history or reputation), and no more specific flag explains the held verdict.",
        "operationId": "domain_bulk_alias",
        "tags": [
          "Core Verification"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [],
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "cURL",
            "source": "curl -sS -X POST \"https://api.emailscore.io/v1/domain/bulk\" \\\n  -H \"Authorization: Bearer YOUR_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Accept-Encoding: gzip\" \\\n  -d '{\"domains\": [\"google.com\", \"gmial.com\", \"not a domain\"]}'"
          },
          {
            "lang": "Ruby",
            "label": "Ruby",
            "source": "require 'net/http'\nrequire 'uri'\nrequire 'json'\n\nuri = URI('https://api.emailscore.io/v1/domain/bulk')\nhttp = Net::HTTP.new(uri.host, uri.port)\nhttp.use_ssl = true\n\nreq = Net::HTTP::Post.new(uri.path, {\n  'Authorization' => 'Bearer YOUR_API_KEY',\n  'Content-Type' => 'application/json',\n  'Accept-Encoding' => 'gzip'\n})\nreq.body = {\n  domains: [\n    'google.com',\n    'gmial.com',\n    'not a domain'\n  ]\n}.to_json\n\nres = http.request(req)\nbatch = JSON.parse(res.body)\n\nputs \"Scored #{batch['processed']}/#{batch['total']} in #{batch['evaluation_time_ms']}ms\"\nputs \"Summary: Allow=#{batch.dig('summary', 'allow')}, Deny=#{batch.dig('summary', 'deny')}\"\n\nbatch['results'].each do |item|\n  puts \"  [#{item['decision'].upcase}] #{item['domain']} -> Score: #{item['score']} #{item['flags'].join(',')}\"\nend"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import requests\n\nurl = \"https://api.emailscore.io/v1/domain/bulk\"\nheaders = {\n    \"Authorization\": \"Bearer YOUR_API_KEY\",\n    \"Content-Type\": \"application/json\",\n    \"Accept-Encoding\": \"gzip\",\n}\npayload = {\n    \"domains\": [\n        \"google.com\",\n        \"gmial.com\",\n        \"not a domain\",\n    ]\n}\n\nresponse = requests.post(url, json=payload, headers=headers)\ndata = response.json()\n\nprint(f\"Total: {data['total']} | Evaluation Time: {data['evaluation_time_ms']}ms\")\nprint(f\"Summary: Allow={data['summary']['allow']}, Deny={data['summary']['deny']}\")\nfor item in data['results']:\n    print(f\" - {item['domain']}: {item['score']} ({item['decision']}) {item['flags']}\")"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "// Bulk / Batch Domain Check (up to 10,000 domains per request)\nconst response = await fetch('https://api.emailscore.io/v1/domain/bulk', {\n  method: 'POST',\n  headers: {\n    'Authorization': 'Bearer YOUR_API_KEY',\n    'Content-Type': 'application/json',\n    'Accept-Encoding': 'gzip',\n  },\n  body: JSON.stringify({\n    domains: [\n      'google.com',\n      'gmial.com',\n      'not a domain',\n    ]\n  }),\n});\n\nconst batch = await response.json();\nconsole.log(`Scored ${batch.processed}/${batch.total} in ${batch.evaluation_time_ms}ms`);\nconsole.log('Summary:', batch.summary); // { allow: 1, challenge: 0, deny: 2 }"
          },
          {
            "lang": "Go",
            "label": "Go",
            "source": "package main\n\nimport (\n    \"bytes\"\n    \"fmt\"\n    \"io\"\n    \"net/http\"\n)\n\nfunc main() {\n    url := \"https://api.emailscore.io/v1/domain/bulk\"\n    payload := []byte(`{\"domains\": [\"google.com\", \"gmial.com\", \"not a domain\"]}`)\n\n    req, err := http.NewRequest(\"POST\", url, bytes.NewBuffer(payload))\n    if err != nil {\n        panic(err)\n    }\n\n    req.Header.Set(\"Authorization\", \"Bearer YOUR_API_KEY\")\n    req.Header.Set(\"Content-Type\", \"application/json\")\n    req.Header.Set(\"Accept-Encoding\", \"gzip\")\n\n    client := &http.Client{}\n    resp, err := client.Do(req)\n    if err != nil {\n        panic(err)\n    }\n    defer resp.Body.Close()\n\n    body, _ := io.ReadAll(resp.Body)\n    fmt.Println(string(body))\n}"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.emailscore.io/v1/domain/bulk\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_POST, true);\ncurl_setopt($ch, CURLOPT_ENCODING, \"gzip\");\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    'Authorization: Bearer YOUR_API_KEY',\n    'Content-Type: application/json',\n    'Accept-Encoding: gzip'\n]);\ncurl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([\n    'domains' => [\n        'google.com',\n        'gmial.com',\n        'not a domain'\n    ]\n]));\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\n$batch = json_decode($response, true);\necho \"Scored \" . $batch['processed'] . \"/\" . $batch['total'] . \" in \" . $batch['evaluation_time_ms'] . \"ms\\n\";"
          },
          {
            "lang": "Rust",
            "label": "Rust",
            "source": "use reqwest::header::{ACCEPT_ENCODING, AUTHORIZATION, CONTENT_TYPE};\nuse serde_json::{json, Value};\n\n#[tokio::main]\nasync fn main() -> Result<(), Box<dyn std::error::Error>> {\n    let client = reqwest::Client::new();\n    let res = client\n        .post(\"https://api.emailscore.io/v1/domain/bulk\")\n        .header(AUTHORIZATION, \"Bearer YOUR_API_KEY\")\n        .header(CONTENT_TYPE, \"application/json\")\n        .header(ACCEPT_ENCODING, \"gzip\")\n        .json(&json!({\n            \"domains\": [\n                \"google.com\",\n                \"gmial.com\",\n                \"not a domain\"\n            ]\n        }))\n        .send()\n        .await?;\n\n    let batch: Value = res.json().await?;\n    println!(\"Processed: {}/{}\", batch[\"processed\"], batch[\"total\"]);\n    println!(\"Summary: {}\", batch[\"summary\"]);\n    Ok(())\n}"
          }
        ],
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "cURL",
            "source": "curl -sS -X POST \"https://api.emailscore.io/v1/domain/bulk\" \\\n  -H \"Authorization: Bearer YOUR_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Accept-Encoding: gzip\" \\\n  -d '{\"domains\": [\"google.com\", \"gmial.com\", \"not a domain\"]}'"
          },
          {
            "lang": "Ruby",
            "label": "Ruby",
            "source": "require 'net/http'\nrequire 'uri'\nrequire 'json'\n\nuri = URI('https://api.emailscore.io/v1/domain/bulk')\nhttp = Net::HTTP.new(uri.host, uri.port)\nhttp.use_ssl = true\n\nreq = Net::HTTP::Post.new(uri.path, {\n  'Authorization' => 'Bearer YOUR_API_KEY',\n  'Content-Type' => 'application/json',\n  'Accept-Encoding' => 'gzip'\n})\nreq.body = {\n  domains: [\n    'google.com',\n    'gmial.com',\n    'not a domain'\n  ]\n}.to_json\n\nres = http.request(req)\nbatch = JSON.parse(res.body)\n\nputs \"Scored #{batch['processed']}/#{batch['total']} in #{batch['evaluation_time_ms']}ms\"\nputs \"Summary: Allow=#{batch.dig('summary', 'allow')}, Deny=#{batch.dig('summary', 'deny')}\"\n\nbatch['results'].each do |item|\n  puts \"  [#{item['decision'].upcase}] #{item['domain']} -> Score: #{item['score']} #{item['flags'].join(',')}\"\nend"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import requests\n\nurl = \"https://api.emailscore.io/v1/domain/bulk\"\nheaders = {\n    \"Authorization\": \"Bearer YOUR_API_KEY\",\n    \"Content-Type\": \"application/json\",\n    \"Accept-Encoding\": \"gzip\",\n}\npayload = {\n    \"domains\": [\n        \"google.com\",\n        \"gmial.com\",\n        \"not a domain\",\n    ]\n}\n\nresponse = requests.post(url, json=payload, headers=headers)\ndata = response.json()\n\nprint(f\"Total: {data['total']} | Evaluation Time: {data['evaluation_time_ms']}ms\")\nprint(f\"Summary: Allow={data['summary']['allow']}, Deny={data['summary']['deny']}\")\nfor item in data['results']:\n    print(f\" - {item['domain']}: {item['score']} ({item['decision']}) {item['flags']}\")"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "// Bulk / Batch Domain Check (up to 10,000 domains per request)\nconst response = await fetch('https://api.emailscore.io/v1/domain/bulk', {\n  method: 'POST',\n  headers: {\n    'Authorization': 'Bearer YOUR_API_KEY',\n    'Content-Type': 'application/json',\n    'Accept-Encoding': 'gzip',\n  },\n  body: JSON.stringify({\n    domains: [\n      'google.com',\n      'gmial.com',\n      'not a domain',\n    ]\n  }),\n});\n\nconst batch = await response.json();\nconsole.log(`Scored ${batch.processed}/${batch.total} in ${batch.evaluation_time_ms}ms`);\nconsole.log('Summary:', batch.summary); // { allow: 1, challenge: 0, deny: 2 }"
          },
          {
            "lang": "Go",
            "label": "Go",
            "source": "package main\n\nimport (\n    \"bytes\"\n    \"fmt\"\n    \"io\"\n    \"net/http\"\n)\n\nfunc main() {\n    url := \"https://api.emailscore.io/v1/domain/bulk\"\n    payload := []byte(`{\"domains\": [\"google.com\", \"gmial.com\", \"not a domain\"]}`)\n\n    req, err := http.NewRequest(\"POST\", url, bytes.NewBuffer(payload))\n    if err != nil {\n        panic(err)\n    }\n\n    req.Header.Set(\"Authorization\", \"Bearer YOUR_API_KEY\")\n    req.Header.Set(\"Content-Type\", \"application/json\")\n    req.Header.Set(\"Accept-Encoding\", \"gzip\")\n\n    client := &http.Client{}\n    resp, err := client.Do(req)\n    if err != nil {\n        panic(err)\n    }\n    defer resp.Body.Close()\n\n    body, _ := io.ReadAll(resp.Body)\n    fmt.Println(string(body))\n}"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.emailscore.io/v1/domain/bulk\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_POST, true);\ncurl_setopt($ch, CURLOPT_ENCODING, \"gzip\");\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    'Authorization: Bearer YOUR_API_KEY',\n    'Content-Type: application/json',\n    'Accept-Encoding: gzip'\n]);\ncurl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([\n    'domains' => [\n        'google.com',\n        'gmial.com',\n        'not a domain'\n    ]\n]));\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\n$batch = json_decode($response, true);\necho \"Scored \" . $batch['processed'] . \"/\" . $batch['total'] . \" in \" . $batch['evaluation_time_ms'] . \"ms\\n\";"
          },
          {
            "lang": "Rust",
            "label": "Rust",
            "source": "use reqwest::header::{ACCEPT_ENCODING, AUTHORIZATION, CONTENT_TYPE};\nuse serde_json::{json, Value};\n\n#[tokio::main]\nasync fn main() -> Result<(), Box<dyn std::error::Error>> {\n    let client = reqwest::Client::new();\n    let res = client\n        .post(\"https://api.emailscore.io/v1/domain/bulk\")\n        .header(AUTHORIZATION, \"Bearer YOUR_API_KEY\")\n        .header(CONTENT_TYPE, \"application/json\")\n        .header(ACCEPT_ENCODING, \"gzip\")\n        .json(&json!({\n            \"domains\": [\n                \"google.com\",\n                \"gmial.com\",\n                \"not a domain\"\n            ]\n        }))\n        .send()\n        .await?;\n\n    let batch: Value = res.json().await?;\n    println!(\"Processed: {}/{}\", batch[\"processed\"], batch[\"total\"]);\n    println!(\"Summary: {}\", batch[\"summary\"]);\n    Ok(())\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "Batch completed. Returns summary counts and one result per submitted domain, in submission order.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "total": {
                      "type": "integer",
                      "description": "Number of domains received in the batch."
                    },
                    "processed": {
                      "type": "integer",
                      "description": "Number of domains evaluated."
                    },
                    "evaluation_time_ms": {
                      "type": "number",
                      "description": "Total server-side processing duration in milliseconds for the batch."
                    },
                    "summary": {
                      "type": "object",
                      "description": "Decision counts across the batch.",
                      "properties": {
                        "allow": {
                          "type": "integer",
                          "description": "Domains with an `allow` decision."
                        },
                        "challenge": {
                          "type": "integer",
                          "description": "Domains with a `challenge` decision."
                        },
                        "deny": {
                          "type": "integer",
                          "description": "Domains with a `deny` decision, including invalid entries."
                        }
                      }
                    },
                    "results": {
                      "type": "array",
                      "description": "Per-domain verdicts in submission order. Each equals the `/v1/domain` result for that domain without `domain_quality`, `dns`, and `evaluation_time_ms`.",
                      "items": {
                        "type": "object",
                        "properties": {
                          "domain": {
                            "type": "string",
                            "description": "Normalized domain (trimmed, lowercased, trailing dot removed), or the trimmed input for an invalid entry."
                          },
                          "score": {
                            "type": "integer",
                            "description": "Domain risk score from 0 to 100."
                          },
                          "decision": {
                            "type": "string",
                            "enum": [
                              "allow",
                              "challenge",
                              "deny"
                            ],
                            "description": "Recommendation for the domain: `allow`, `challenge`, or `deny`."
                          },
                          "risk_level": {
                            "type": "string",
                            "enum": [
                              "low",
                              "medium",
                              "high",
                              "critical"
                            ],
                            "description": "Categorical risk assessment."
                          },
                          "recommendation": {
                            "type": "string",
                            "description": "Short explanation of the decision."
                          },
                          "flags": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            },
                            "description": "Domain risk flags (listed in the endpoint description). Empty array for a clean domain."
                          },
                          "evidence": {
                            "type": "string",
                            "enum": [
                              "complete",
                              "partial"
                            ],
                            "description": "`complete` when DNS was looked up. `partial` when it was not, so MX, SPF, and DMARC are unknown."
                          },
                          "did_you_mean": {
                            "type": "string",
                            "nullable": true,
                            "description": "Suggested domain when the input looks like a typo of a known provider, else null."
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "total": 3,
                  "processed": 3,
                  "evaluation_time_ms": 41.7,
                  "summary": {
                    "allow": 1,
                    "challenge": 0,
                    "deny": 2
                  },
                  "results": [
                    {
                      "domain": "google.com",
                      "score": 100,
                      "decision": "allow",
                      "risk_level": "low",
                      "recommendation": "Allow: established domain with working mail.",
                      "flags": [],
                      "evidence": "complete",
                      "did_you_mean": null
                    },
                    {
                      "domain": "gmial.com",
                      "score": 0,
                      "decision": "deny",
                      "risk_level": "critical",
                      "recommendation": "Deny: disposable or temporary email addresses are not accepted.",
                      "flags": [
                        "TYPO_DOMAIN_SUGGESTION",
                        "DOMAIN_TYPO_SUSPECTED",
                        "DISPOSABLE_DOMAIN"
                      ],
                      "evidence": "partial",
                      "did_you_mean": "gmail.com"
                    },
                    {
                      "domain": "not a domain",
                      "score": 0,
                      "decision": "deny",
                      "risk_level": "critical",
                      "recommendation": "Deny: not a valid domain.",
                      "flags": [
                        "INVALID_FORMAT"
                      ],
                      "evidence": "partial",
                      "did_you_mean": null
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Empty `domains` array (`{\"error\": \"Domains array cannot be empty\"}`), invalid request body, or more than 10,000 domains.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Batch validation error message."
                    },
                    "max_batch_size": {
                      "type": "integer",
                      "description": "Maximum domains per request. Present only when the batch is too large."
                    },
                    "received": {
                      "type": "integer",
                      "description": "Number of domains submitted. Present only when the batch is too large."
                    }
                  }
                },
                "example": {
                  "error": "Batch size exceeds maximum limit of 10000 domains per request. Please submit in batches of up to 10000.",
                  "max_batch_size": 10000,
                  "received": 10001
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Authentication failure reason."
                    }
                  }
                },
                "example": {
                  "error": "Invalid or revoked API key"
                }
              }
            }
          },
          "403": {
            "description": "Guest trial token (`es_temp_...`) used on a bulk endpoint. Register for an API key.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Machine-readable reason: `registration_required`."
                    },
                    "message": {
                      "type": "string",
                      "description": "Guidance for obtaining an API key."
                    }
                  }
                },
                "example": {
                  "error": "registration_required"
                }
              }
            }
          },
          "429": {
            "description": "Two causes. `rate_limited`: more requests per second than your plan allows. The limit applies to your whole account, across all its API keys; the response carries `Retry-After` (seconds) and `X-Request-Rate-Limit`, and the request uses no credits. Quota: a free Developer allowance is used up with no credit pack balance (paid plans are never blocked by quota; checks past the allowance are billed at the plan's rate).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "`rate_limited`, or a message describing the exhausted allowance."
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable explanation, including when to retry."
                    },
                    "requests_per_second": {
                      "type": "integer",
                      "description": "Your plan's request rate (present when `error` is `rate_limited`)."
                    }
                  }
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Request rate limit reached: 25 requests per second. Retry after 1 second. Bulk endpoints check up to 10000 items in one request.",
                  "requests_per_second": 25
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "domains": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "required": true,
                    "example": [
                      "google.com",
                      "gmial.com",
                      "not a domain"
                    ],
                    "description": "Array of domains to score (1 to 10,000 per request). A raw JSON array of strings is also accepted as the whole body."
                  }
                }
              },
              "example": {
                "domains": [
                  "google.com",
                  "gmial.com",
                  "not a domain"
                ]
              }
            }
          }
        }
      }
    },
    "/v1/bounce/diagnose": {
      "post": {
        "summary": "Parse raw SMTP error diagnostics into structured deliverability actions",
        "description": "Classify supplied mailserver error messages and recommend a next action, such as\nsuppressing a permanently failed address, retrying a temporary failure, or investigating a block.\nThis analyzes a delivery failure that has already occurred; it does not predict a future bounce.\n\nMetered at **5 credits** per diagnosis. Processing can use an external service when configured;\ndo not assume that all diagnostics are evaluated offline.",
        "operationId": "bounce_diagnose",
        "tags": [
          "Post-Flight Diagnostics"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [],
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "cURL",
            "source": "curl -sS -X POST \"https://api.emailscore.io/v1/bounce/diagnose\" \\\n  -H \"Authorization: Bearer YOUR_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"diagnostic\": \"550 5.1.1 <user@example.com>: Recipient address rejected: User unknown in virtual mailbox table\", \"email\": \"user@example.com\"}'"
          },
          {
            "lang": "Ruby",
            "label": "Ruby",
            "source": "require 'net/http'\nrequire 'uri'\nrequire 'json'\n\nuri = URI('https://api.emailscore.io/v1/bounce/diagnose')\nhttp = Net::HTTP.new(uri.host, uri.port)\nhttp.use_ssl = true\n\nreq = Net::HTTP::Post.new(uri.path, {\n  'Authorization' => 'Bearer YOUR_API_KEY',\n  'Content-Type' => 'application/json'\n})\nreq.body = {\n  diagnostic: '550 5.1.1 <user@example.com>: Recipient address rejected: User unknown in virtual mailbox table',\n  email: 'user@example.com'\n}.to_json\n\nres = http.request(req)\ntriage = JSON.parse(res.body)\n\nputs \"Action: #{triage['action']} | Category: #{triage['category']}\"\nputs \"Hard Bounce Probability: #{(triage['permanent_hard_bounce_probability'] * 100).round}%\"\nputs \"Recommendation: #{triage['recommendation']}\"\n\nif triage['action'] == 'prune_permanent'\n  # Mailbox does not exist: purge from recipient list\n  puts \"Purging dead address: #{triage['email']}\"\nelse\n  # Temporary failure (quota/greylist): safe to retry\n  puts \"Transient bounce: queuing retry for #{triage['email']}\"\nend"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import requests\n\nurl = \"https://api.emailscore.io/v1/bounce/diagnose\"\nheaders = {\n    \"Authorization\": \"Bearer YOUR_API_KEY\",\n    \"Content-Type\": \"application/json\",\n}\npayload = {\n    \"diagnostic\": \"550 5.1.1 <user@example.com>: Recipient address rejected: User unknown in virtual mailbox table\",\n    \"email\": \"user@example.com\",\n}\n\nresponse = requests.post(url, json=payload, headers=headers)\ndata = response.json()\n\nprint(f\"Action: {data['action'].upper()} -> Category: {data['category']}\")\nprint(f\"Probability: {data['permanent_hard_bounce_probability'] * 100:.0f}%\")\nprint(f\"Recommendation: {data['recommendation']}\")\n\nif data[\"action\"] == \"prune_permanent\":\n    suppress_contact(data.get(\"email\"))\nelse:\n    schedule_retry(data.get(\"email\"))"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "// Post-Flight SMTP Bounce Triage (5 credits)\nconst response = await fetch('https://api.emailscore.io/v1/bounce/diagnose', {\n  method: 'POST',\n  headers: {\n    'Authorization': 'Bearer YOUR_API_KEY',\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    diagnostic: '550 5.1.1 <user@example.com>: Recipient address rejected: User unknown',\n    email: 'user@example.com',\n  }),\n});\n\nconst triage = await response.json();\nconsole.log(`Action: ${triage.action} | Category: ${triage.category}`);\nconsole.log(`Hard Bounce Probability: ${(triage.permanent_hard_bounce_probability * 100).toFixed(0)}%`);\n\nif (triage.action === 'prune_permanent') {\n  // Purge dead mailbox from mailing list\n  await suppressContact(triage.email);\n} else {\n  // Safe to retry transient failure\n  await scheduleRetry(triage.email);\n}"
          },
          {
            "lang": "Go",
            "label": "Go",
            "source": "package main\n\nimport (\n    \"bytes\"\n    \"fmt\"\n    \"io\"\n    \"net/http\"\n)\n\nfunc main() {\n    url := \"https://api.emailscore.io/v1/bounce/diagnose\"\n    payload := []byte(`{\n        \"diagnostic\": \"550 5.1.1 <user@example.com>: Recipient address rejected: User unknown\",\n        \"email\": \"user@example.com\"\n    }`)\n\n    req, err := http.NewRequest(\"POST\", url, bytes.NewBuffer(payload))\n    if err != nil {\n        panic(err)\n    }\n\n    req.Header.Set(\"Authorization\", \"Bearer YOUR_API_KEY\")\n    req.Header.Set(\"Content-Type\", \"application/json\")\n\n    client := &http.Client{}\n    resp, err := client.Do(req)\n    if err != nil {\n        panic(err)\n    }\n    defer resp.Body.Close()\n\n    body, _ := io.ReadAll(resp.Body)\n    fmt.Println(string(body))\n}"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.emailscore.io/v1/bounce/diagnose\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_POST, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    'Authorization: Bearer YOUR_API_KEY',\n    'Content-Type: application/json'\n]);\ncurl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([\n    'diagnostic' => '550 5.1.1 <user@example.com>: Recipient address rejected: User unknown in virtual mailbox table',\n    'email' => 'user@example.com'\n]));\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\n$triage = json_decode($response, true);\necho \"Action: \" . $triage['action'] . \" | Category: \" . $triage['category'] . \"\\n\";\nif ($triage['action'] === 'prune_permanent') {\n    suppress_contact($triage['email']);\n}"
          },
          {
            "lang": "Rust",
            "label": "Rust",
            "source": "use reqwest::header::{AUTHORIZATION, CONTENT_TYPE};\nuse serde_json::{json, Value};\n\n#[tokio::main]\nasync fn main() -> Result<(), Box<dyn std::error::Error>> {\n    let client = reqwest::Client::new();\n    let res = client\n        .post(\"https://api.emailscore.io/v1/bounce/diagnose\")\n        .header(AUTHORIZATION, \"Bearer YOUR_API_KEY\")\n        .header(CONTENT_TYPE, \"application/json\")\n        .json(&json!({\n            \"diagnostic\": \"550 5.1.1 <user@example.com>: Recipient address rejected: User unknown\",\n            \"email\": \"user@example.com\"\n        }))\n        .send()\n        .await?;\n\n    let json: Value = res.json().await?;\n    println!(\"Action: {} | Category: {}\", json[\"action\"], json[\"category\"]);\n    println!(\"Recommendation: {}\", json[\"recommendation\"]);\n    Ok(())\n}"
          }
        ],
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "cURL",
            "source": "curl -sS -X POST \"https://api.emailscore.io/v1/bounce/diagnose\" \\\n  -H \"Authorization: Bearer YOUR_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"diagnostic\": \"550 5.1.1 <user@example.com>: Recipient address rejected: User unknown in virtual mailbox table\", \"email\": \"user@example.com\"}'"
          },
          {
            "lang": "Ruby",
            "label": "Ruby",
            "source": "require 'net/http'\nrequire 'uri'\nrequire 'json'\n\nuri = URI('https://api.emailscore.io/v1/bounce/diagnose')\nhttp = Net::HTTP.new(uri.host, uri.port)\nhttp.use_ssl = true\n\nreq = Net::HTTP::Post.new(uri.path, {\n  'Authorization' => 'Bearer YOUR_API_KEY',\n  'Content-Type' => 'application/json'\n})\nreq.body = {\n  diagnostic: '550 5.1.1 <user@example.com>: Recipient address rejected: User unknown in virtual mailbox table',\n  email: 'user@example.com'\n}.to_json\n\nres = http.request(req)\ntriage = JSON.parse(res.body)\n\nputs \"Action: #{triage['action']} | Category: #{triage['category']}\"\nputs \"Hard Bounce Probability: #{(triage['permanent_hard_bounce_probability'] * 100).round}%\"\nputs \"Recommendation: #{triage['recommendation']}\"\n\nif triage['action'] == 'prune_permanent'\n  # Mailbox does not exist: purge from recipient list\n  puts \"Purging dead address: #{triage['email']}\"\nelse\n  # Temporary failure (quota/greylist): safe to retry\n  puts \"Transient bounce: queuing retry for #{triage['email']}\"\nend"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import requests\n\nurl = \"https://api.emailscore.io/v1/bounce/diagnose\"\nheaders = {\n    \"Authorization\": \"Bearer YOUR_API_KEY\",\n    \"Content-Type\": \"application/json\",\n}\npayload = {\n    \"diagnostic\": \"550 5.1.1 <user@example.com>: Recipient address rejected: User unknown in virtual mailbox table\",\n    \"email\": \"user@example.com\",\n}\n\nresponse = requests.post(url, json=payload, headers=headers)\ndata = response.json()\n\nprint(f\"Action: {data['action'].upper()} -> Category: {data['category']}\")\nprint(f\"Probability: {data['permanent_hard_bounce_probability'] * 100:.0f}%\")\nprint(f\"Recommendation: {data['recommendation']}\")\n\nif data[\"action\"] == \"prune_permanent\":\n    suppress_contact(data.get(\"email\"))\nelse:\n    schedule_retry(data.get(\"email\"))"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "// Post-Flight SMTP Bounce Triage (5 credits)\nconst response = await fetch('https://api.emailscore.io/v1/bounce/diagnose', {\n  method: 'POST',\n  headers: {\n    'Authorization': 'Bearer YOUR_API_KEY',\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    diagnostic: '550 5.1.1 <user@example.com>: Recipient address rejected: User unknown',\n    email: 'user@example.com',\n  }),\n});\n\nconst triage = await response.json();\nconsole.log(`Action: ${triage.action} | Category: ${triage.category}`);\nconsole.log(`Hard Bounce Probability: ${(triage.permanent_hard_bounce_probability * 100).toFixed(0)}%`);\n\nif (triage.action === 'prune_permanent') {\n  // Purge dead mailbox from mailing list\n  await suppressContact(triage.email);\n} else {\n  // Safe to retry transient failure\n  await scheduleRetry(triage.email);\n}"
          },
          {
            "lang": "Go",
            "label": "Go",
            "source": "package main\n\nimport (\n    \"bytes\"\n    \"fmt\"\n    \"io\"\n    \"net/http\"\n)\n\nfunc main() {\n    url := \"https://api.emailscore.io/v1/bounce/diagnose\"\n    payload := []byte(`{\n        \"diagnostic\": \"550 5.1.1 <user@example.com>: Recipient address rejected: User unknown\",\n        \"email\": \"user@example.com\"\n    }`)\n\n    req, err := http.NewRequest(\"POST\", url, bytes.NewBuffer(payload))\n    if err != nil {\n        panic(err)\n    }\n\n    req.Header.Set(\"Authorization\", \"Bearer YOUR_API_KEY\")\n    req.Header.Set(\"Content-Type\", \"application/json\")\n\n    client := &http.Client{}\n    resp, err := client.Do(req)\n    if err != nil {\n        panic(err)\n    }\n    defer resp.Body.Close()\n\n    body, _ := io.ReadAll(resp.Body)\n    fmt.Println(string(body))\n}"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.emailscore.io/v1/bounce/diagnose\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_POST, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    'Authorization: Bearer YOUR_API_KEY',\n    'Content-Type: application/json'\n]);\ncurl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([\n    'diagnostic' => '550 5.1.1 <user@example.com>: Recipient address rejected: User unknown in virtual mailbox table',\n    'email' => 'user@example.com'\n]));\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\n$triage = json_decode($response, true);\necho \"Action: \" . $triage['action'] . \" | Category: \" . $triage['category'] . \"\\n\";\nif ($triage['action'] === 'prune_permanent') {\n    suppress_contact($triage['email']);\n}"
          },
          {
            "lang": "Rust",
            "label": "Rust",
            "source": "use reqwest::header::{AUTHORIZATION, CONTENT_TYPE};\nuse serde_json::{json, Value};\n\n#[tokio::main]\nasync fn main() -> Result<(), Box<dyn std::error::Error>> {\n    let client = reqwest::Client::new();\n    let res = client\n        .post(\"https://api.emailscore.io/v1/bounce/diagnose\")\n        .header(AUTHORIZATION, \"Bearer YOUR_API_KEY\")\n        .header(CONTENT_TYPE, \"application/json\")\n        .json(&json!({\n            \"diagnostic\": \"550 5.1.1 <user@example.com>: Recipient address rejected: User unknown\",\n            \"email\": \"user@example.com\"\n        }))\n        .send()\n        .await?;\n\n    let json: Value = res.json().await?;\n    println!(\"Action: {} | Category: {}\", json[\"action\"], json[\"category\"]);\n    println!(\"Recommendation: {}\", json[\"recommendation\"]);\n    Ok(())\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "Diagnostic evaluation successful. Returns structured deliverability action and RFC category.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "diagnostic": {
                      "type": "string",
                      "required": true,
                      "description": "Echo of the input diagnostic string."
                    },
                    "email": {
                      "type": "string",
                      "required": false,
                      "description": "Associated email address if provided in request."
                    },
                    "category": {
                      "type": "string",
                      "required": true,
                      "enum": [
                        "hard_bounce_user_unknown",
                        "soft_bounce_mailbox_full",
                        "ip_or_domain_blacklisted",
                        "authentication_failure",
                        "transient_network_timeout"
                      ],
                      "description": "Standard RFC deliverability classification."
                    },
                    "action": {
                      "type": "string",
                      "required": true,
                      "enum": [
                        "prune_permanent",
                        "retry_transient"
                      ],
                      "description": "Recommended handling of the supplied failure: review permanent suppression for `prune_permanent`, or retry policy for `retry_transient`."
                    },
                    "permanent_hard_bounce_probability": {
                      "type": "number",
                      "required": true,
                      "description": "Probability [0.0 to 1.0] that this bounce is an unrecoverable hard bounce."
                    },
                    "confidence": {
                      "type": "number",
                      "required": true,
                      "description": "Confidence level of category classification."
                    },
                    "recommendation": {
                      "type": "string",
                      "required": true,
                      "description": "Concrete engineering and deliverability guidance."
                    },
                    "evaluation_time_ms": {
                      "type": "number",
                      "required": true,
                      "description": "Processing latency in milliseconds."
                    }
                  }
                },
                "example": {
                  "diagnostic": "550 5.1.1 <user@example.com>: Recipient address rejected: User unknown in virtual mailbox table",
                  "email": "user@example.com",
                  "category": "hard_bounce_user_unknown",
                  "action": "prune_permanent",
                  "permanent_hard_bounce_probability": 0.96,
                  "confidence": 1,
                  "recommendation": "Permanently remove recipient address from mailing lists. Mailbox does not exist or was rejected permanently by the target server.",
                  "evaluation_time_ms": 245.8
                }
              }
            }
          },
          "400": {
            "description": "Invalid request payload or batch size exceeds 1,000 items.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Reason the request was rejected."
                    }
                  }
                },
                "example": {
                  "error": "Batch size exceeds maximum limit of 1,000 bounce diagnostics per request."
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Authentication error code."
                    },
                    "message": {
                      "type": "string",
                      "description": "Guidance for providing valid API key."
                    }
                  }
                },
                "example": {
                  "error": "authentication_required",
                  "message": "API key required. Provide 'Authorization: Bearer <key>'."
                }
              }
            }
          },
          "429": {
            "description": "Insufficient PAYG credits (5 credits per diagnosis).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error",
                    "required_credits",
                    "payg_credits_remaining"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Credit exhaustion explanation."
                    },
                    "required_credits": {
                      "type": "integer",
                      "description": "Credits needed for requested operation."
                    },
                    "payg_credits_remaining": {
                      "type": "integer",
                      "description": "Available PAYG credit balance."
                    }
                  }
                },
                "example": {
                  "error": "Insufficient credits: diagnosing 1 bounce(s) requires 5 credits (0 available).",
                  "required_credits": 5,
                  "payg_credits_remaining": 0
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "diagnostic": {
                    "type": "string",
                    "required": true,
                    "example": "550 5.1.1 <user@example.com>: Recipient address rejected: User unknown in virtual mailbox table",
                    "description": "The raw SMTP response line or error string returned by the receiving mailserver."
                  },
                  "email": {
                    "type": "string",
                    "required": false,
                    "example": "user@example.com",
                    "description": "Optional recipient email address associated with the bounce event."
                  }
                }
              },
              "example": {
                "diagnostic": "550 5.1.1 <user@example.com>: Recipient address rejected: User unknown in virtual mailbox table",
                "email": "user@example.com"
              }
            }
          }
        }
      }
    },
    "/v1/bounce/batch": {
      "post": {
        "summary": "Parse raw SMTP error diagnostics into structured deliverability actions (Alias)",
        "description": "Classify supplied mailserver error messages and recommend a next action, such as\nsuppressing a permanently failed address, retrying a temporary failure, or investigating a block.\nThis analyzes a delivery failure that has already occurred; it does not predict a future bounce.\n\nMetered at **5 credits** per diagnosis. Processing can use an external service when configured;\ndo not assume that all diagnostics are evaluated offline.",
        "operationId": "bounce_diagnose_alias",
        "tags": [
          "Post-Flight Diagnostics"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [],
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "cURL",
            "source": "curl -sS -X POST \"https://api.emailscore.io/v1/bounce/diagnose\" \\\n  -H \"Authorization: Bearer YOUR_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"diagnostic\": \"550 5.1.1 <user@example.com>: Recipient address rejected: User unknown in virtual mailbox table\", \"email\": \"user@example.com\"}'"
          },
          {
            "lang": "Ruby",
            "label": "Ruby",
            "source": "require 'net/http'\nrequire 'uri'\nrequire 'json'\n\nuri = URI('https://api.emailscore.io/v1/bounce/diagnose')\nhttp = Net::HTTP.new(uri.host, uri.port)\nhttp.use_ssl = true\n\nreq = Net::HTTP::Post.new(uri.path, {\n  'Authorization' => 'Bearer YOUR_API_KEY',\n  'Content-Type' => 'application/json'\n})\nreq.body = {\n  diagnostic: '550 5.1.1 <user@example.com>: Recipient address rejected: User unknown in virtual mailbox table',\n  email: 'user@example.com'\n}.to_json\n\nres = http.request(req)\ntriage = JSON.parse(res.body)\n\nputs \"Action: #{triage['action']} | Category: #{triage['category']}\"\nputs \"Hard Bounce Probability: #{(triage['permanent_hard_bounce_probability'] * 100).round}%\"\nputs \"Recommendation: #{triage['recommendation']}\"\n\nif triage['action'] == 'prune_permanent'\n  # Mailbox does not exist: purge from recipient list\n  puts \"Purging dead address: #{triage['email']}\"\nelse\n  # Temporary failure (quota/greylist): safe to retry\n  puts \"Transient bounce: queuing retry for #{triage['email']}\"\nend"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import requests\n\nurl = \"https://api.emailscore.io/v1/bounce/diagnose\"\nheaders = {\n    \"Authorization\": \"Bearer YOUR_API_KEY\",\n    \"Content-Type\": \"application/json\",\n}\npayload = {\n    \"diagnostic\": \"550 5.1.1 <user@example.com>: Recipient address rejected: User unknown in virtual mailbox table\",\n    \"email\": \"user@example.com\",\n}\n\nresponse = requests.post(url, json=payload, headers=headers)\ndata = response.json()\n\nprint(f\"Action: {data['action'].upper()} -> Category: {data['category']}\")\nprint(f\"Probability: {data['permanent_hard_bounce_probability'] * 100:.0f}%\")\nprint(f\"Recommendation: {data['recommendation']}\")\n\nif data[\"action\"] == \"prune_permanent\":\n    suppress_contact(data.get(\"email\"))\nelse:\n    schedule_retry(data.get(\"email\"))"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "// Post-Flight SMTP Bounce Triage (5 credits)\nconst response = await fetch('https://api.emailscore.io/v1/bounce/diagnose', {\n  method: 'POST',\n  headers: {\n    'Authorization': 'Bearer YOUR_API_KEY',\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    diagnostic: '550 5.1.1 <user@example.com>: Recipient address rejected: User unknown',\n    email: 'user@example.com',\n  }),\n});\n\nconst triage = await response.json();\nconsole.log(`Action: ${triage.action} | Category: ${triage.category}`);\nconsole.log(`Hard Bounce Probability: ${(triage.permanent_hard_bounce_probability * 100).toFixed(0)}%`);\n\nif (triage.action === 'prune_permanent') {\n  // Purge dead mailbox from mailing list\n  await suppressContact(triage.email);\n} else {\n  // Safe to retry transient failure\n  await scheduleRetry(triage.email);\n}"
          },
          {
            "lang": "Go",
            "label": "Go",
            "source": "package main\n\nimport (\n    \"bytes\"\n    \"fmt\"\n    \"io\"\n    \"net/http\"\n)\n\nfunc main() {\n    url := \"https://api.emailscore.io/v1/bounce/diagnose\"\n    payload := []byte(`{\n        \"diagnostic\": \"550 5.1.1 <user@example.com>: Recipient address rejected: User unknown\",\n        \"email\": \"user@example.com\"\n    }`)\n\n    req, err := http.NewRequest(\"POST\", url, bytes.NewBuffer(payload))\n    if err != nil {\n        panic(err)\n    }\n\n    req.Header.Set(\"Authorization\", \"Bearer YOUR_API_KEY\")\n    req.Header.Set(\"Content-Type\", \"application/json\")\n\n    client := &http.Client{}\n    resp, err := client.Do(req)\n    if err != nil {\n        panic(err)\n    }\n    defer resp.Body.Close()\n\n    body, _ := io.ReadAll(resp.Body)\n    fmt.Println(string(body))\n}"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.emailscore.io/v1/bounce/diagnose\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_POST, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    'Authorization: Bearer YOUR_API_KEY',\n    'Content-Type: application/json'\n]);\ncurl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([\n    'diagnostic' => '550 5.1.1 <user@example.com>: Recipient address rejected: User unknown in virtual mailbox table',\n    'email' => 'user@example.com'\n]));\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\n$triage = json_decode($response, true);\necho \"Action: \" . $triage['action'] . \" | Category: \" . $triage['category'] . \"\\n\";\nif ($triage['action'] === 'prune_permanent') {\n    suppress_contact($triage['email']);\n}"
          },
          {
            "lang": "Rust",
            "label": "Rust",
            "source": "use reqwest::header::{AUTHORIZATION, CONTENT_TYPE};\nuse serde_json::{json, Value};\n\n#[tokio::main]\nasync fn main() -> Result<(), Box<dyn std::error::Error>> {\n    let client = reqwest::Client::new();\n    let res = client\n        .post(\"https://api.emailscore.io/v1/bounce/diagnose\")\n        .header(AUTHORIZATION, \"Bearer YOUR_API_KEY\")\n        .header(CONTENT_TYPE, \"application/json\")\n        .json(&json!({\n            \"diagnostic\": \"550 5.1.1 <user@example.com>: Recipient address rejected: User unknown\",\n            \"email\": \"user@example.com\"\n        }))\n        .send()\n        .await?;\n\n    let json: Value = res.json().await?;\n    println!(\"Action: {} | Category: {}\", json[\"action\"], json[\"category\"]);\n    println!(\"Recommendation: {}\", json[\"recommendation\"]);\n    Ok(())\n}"
          }
        ],
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "cURL",
            "source": "curl -sS -X POST \"https://api.emailscore.io/v1/bounce/diagnose\" \\\n  -H \"Authorization: Bearer YOUR_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"diagnostic\": \"550 5.1.1 <user@example.com>: Recipient address rejected: User unknown in virtual mailbox table\", \"email\": \"user@example.com\"}'"
          },
          {
            "lang": "Ruby",
            "label": "Ruby",
            "source": "require 'net/http'\nrequire 'uri'\nrequire 'json'\n\nuri = URI('https://api.emailscore.io/v1/bounce/diagnose')\nhttp = Net::HTTP.new(uri.host, uri.port)\nhttp.use_ssl = true\n\nreq = Net::HTTP::Post.new(uri.path, {\n  'Authorization' => 'Bearer YOUR_API_KEY',\n  'Content-Type' => 'application/json'\n})\nreq.body = {\n  diagnostic: '550 5.1.1 <user@example.com>: Recipient address rejected: User unknown in virtual mailbox table',\n  email: 'user@example.com'\n}.to_json\n\nres = http.request(req)\ntriage = JSON.parse(res.body)\n\nputs \"Action: #{triage['action']} | Category: #{triage['category']}\"\nputs \"Hard Bounce Probability: #{(triage['permanent_hard_bounce_probability'] * 100).round}%\"\nputs \"Recommendation: #{triage['recommendation']}\"\n\nif triage['action'] == 'prune_permanent'\n  # Mailbox does not exist: purge from recipient list\n  puts \"Purging dead address: #{triage['email']}\"\nelse\n  # Temporary failure (quota/greylist): safe to retry\n  puts \"Transient bounce: queuing retry for #{triage['email']}\"\nend"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import requests\n\nurl = \"https://api.emailscore.io/v1/bounce/diagnose\"\nheaders = {\n    \"Authorization\": \"Bearer YOUR_API_KEY\",\n    \"Content-Type\": \"application/json\",\n}\npayload = {\n    \"diagnostic\": \"550 5.1.1 <user@example.com>: Recipient address rejected: User unknown in virtual mailbox table\",\n    \"email\": \"user@example.com\",\n}\n\nresponse = requests.post(url, json=payload, headers=headers)\ndata = response.json()\n\nprint(f\"Action: {data['action'].upper()} -> Category: {data['category']}\")\nprint(f\"Probability: {data['permanent_hard_bounce_probability'] * 100:.0f}%\")\nprint(f\"Recommendation: {data['recommendation']}\")\n\nif data[\"action\"] == \"prune_permanent\":\n    suppress_contact(data.get(\"email\"))\nelse:\n    schedule_retry(data.get(\"email\"))"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "// Post-Flight SMTP Bounce Triage (5 credits)\nconst response = await fetch('https://api.emailscore.io/v1/bounce/diagnose', {\n  method: 'POST',\n  headers: {\n    'Authorization': 'Bearer YOUR_API_KEY',\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    diagnostic: '550 5.1.1 <user@example.com>: Recipient address rejected: User unknown',\n    email: 'user@example.com',\n  }),\n});\n\nconst triage = await response.json();\nconsole.log(`Action: ${triage.action} | Category: ${triage.category}`);\nconsole.log(`Hard Bounce Probability: ${(triage.permanent_hard_bounce_probability * 100).toFixed(0)}%`);\n\nif (triage.action === 'prune_permanent') {\n  // Purge dead mailbox from mailing list\n  await suppressContact(triage.email);\n} else {\n  // Safe to retry transient failure\n  await scheduleRetry(triage.email);\n}"
          },
          {
            "lang": "Go",
            "label": "Go",
            "source": "package main\n\nimport (\n    \"bytes\"\n    \"fmt\"\n    \"io\"\n    \"net/http\"\n)\n\nfunc main() {\n    url := \"https://api.emailscore.io/v1/bounce/diagnose\"\n    payload := []byte(`{\n        \"diagnostic\": \"550 5.1.1 <user@example.com>: Recipient address rejected: User unknown\",\n        \"email\": \"user@example.com\"\n    }`)\n\n    req, err := http.NewRequest(\"POST\", url, bytes.NewBuffer(payload))\n    if err != nil {\n        panic(err)\n    }\n\n    req.Header.Set(\"Authorization\", \"Bearer YOUR_API_KEY\")\n    req.Header.Set(\"Content-Type\", \"application/json\")\n\n    client := &http.Client{}\n    resp, err := client.Do(req)\n    if err != nil {\n        panic(err)\n    }\n    defer resp.Body.Close()\n\n    body, _ := io.ReadAll(resp.Body)\n    fmt.Println(string(body))\n}"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.emailscore.io/v1/bounce/diagnose\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_POST, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    'Authorization: Bearer YOUR_API_KEY',\n    'Content-Type: application/json'\n]);\ncurl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([\n    'diagnostic' => '550 5.1.1 <user@example.com>: Recipient address rejected: User unknown in virtual mailbox table',\n    'email' => 'user@example.com'\n]));\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\n$triage = json_decode($response, true);\necho \"Action: \" . $triage['action'] . \" | Category: \" . $triage['category'] . \"\\n\";\nif ($triage['action'] === 'prune_permanent') {\n    suppress_contact($triage['email']);\n}"
          },
          {
            "lang": "Rust",
            "label": "Rust",
            "source": "use reqwest::header::{AUTHORIZATION, CONTENT_TYPE};\nuse serde_json::{json, Value};\n\n#[tokio::main]\nasync fn main() -> Result<(), Box<dyn std::error::Error>> {\n    let client = reqwest::Client::new();\n    let res = client\n        .post(\"https://api.emailscore.io/v1/bounce/diagnose\")\n        .header(AUTHORIZATION, \"Bearer YOUR_API_KEY\")\n        .header(CONTENT_TYPE, \"application/json\")\n        .json(&json!({\n            \"diagnostic\": \"550 5.1.1 <user@example.com>: Recipient address rejected: User unknown\",\n            \"email\": \"user@example.com\"\n        }))\n        .send()\n        .await?;\n\n    let json: Value = res.json().await?;\n    println!(\"Action: {} | Category: {}\", json[\"action\"], json[\"category\"]);\n    println!(\"Recommendation: {}\", json[\"recommendation\"]);\n    Ok(())\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "Diagnostic evaluation successful. Returns structured deliverability action and RFC category.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "diagnostic": {
                      "type": "string",
                      "required": true,
                      "description": "Echo of the input diagnostic string."
                    },
                    "email": {
                      "type": "string",
                      "required": false,
                      "description": "Associated email address if provided in request."
                    },
                    "category": {
                      "type": "string",
                      "required": true,
                      "enum": [
                        "hard_bounce_user_unknown",
                        "soft_bounce_mailbox_full",
                        "ip_or_domain_blacklisted",
                        "authentication_failure",
                        "transient_network_timeout"
                      ],
                      "description": "Standard RFC deliverability classification."
                    },
                    "action": {
                      "type": "string",
                      "required": true,
                      "enum": [
                        "prune_permanent",
                        "retry_transient"
                      ],
                      "description": "Recommended handling of the supplied failure: review permanent suppression for `prune_permanent`, or retry policy for `retry_transient`."
                    },
                    "permanent_hard_bounce_probability": {
                      "type": "number",
                      "required": true,
                      "description": "Probability [0.0 to 1.0] that this bounce is an unrecoverable hard bounce."
                    },
                    "confidence": {
                      "type": "number",
                      "required": true,
                      "description": "Confidence level of category classification."
                    },
                    "recommendation": {
                      "type": "string",
                      "required": true,
                      "description": "Concrete engineering and deliverability guidance."
                    },
                    "evaluation_time_ms": {
                      "type": "number",
                      "required": true,
                      "description": "Processing latency in milliseconds."
                    }
                  }
                },
                "example": {
                  "diagnostic": "550 5.1.1 <user@example.com>: Recipient address rejected: User unknown in virtual mailbox table",
                  "email": "user@example.com",
                  "category": "hard_bounce_user_unknown",
                  "action": "prune_permanent",
                  "permanent_hard_bounce_probability": 0.96,
                  "confidence": 1,
                  "recommendation": "Permanently remove recipient address from mailing lists. Mailbox does not exist or was rejected permanently by the target server.",
                  "evaluation_time_ms": 245.8
                }
              }
            }
          },
          "400": {
            "description": "Invalid request payload or batch size exceeds 1,000 items.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Reason the request was rejected."
                    }
                  }
                },
                "example": {
                  "error": "Batch size exceeds maximum limit of 1,000 bounce diagnostics per request."
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Authentication error code."
                    },
                    "message": {
                      "type": "string",
                      "description": "Guidance for providing valid API key."
                    }
                  }
                },
                "example": {
                  "error": "authentication_required",
                  "message": "API key required. Provide 'Authorization: Bearer <key>'."
                }
              }
            }
          },
          "429": {
            "description": "Insufficient PAYG credits (5 credits per diagnosis).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error",
                    "required_credits",
                    "payg_credits_remaining"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "Credit exhaustion explanation."
                    },
                    "required_credits": {
                      "type": "integer",
                      "description": "Credits needed for requested operation."
                    },
                    "payg_credits_remaining": {
                      "type": "integer",
                      "description": "Available PAYG credit balance."
                    }
                  }
                },
                "example": {
                  "error": "Insufficient credits: diagnosing 1 bounce(s) requires 5 credits (0 available).",
                  "required_credits": 5,
                  "payg_credits_remaining": 0
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "diagnostic": {
                    "type": "string",
                    "required": true,
                    "example": "550 5.1.1 <user@example.com>: Recipient address rejected: User unknown in virtual mailbox table",
                    "description": "The raw SMTP response line or error string returned by the receiving mailserver."
                  },
                  "email": {
                    "type": "string",
                    "required": false,
                    "example": "user@example.com",
                    "description": "Optional recipient email address associated with the bounce event."
                  }
                }
              },
              "example": {
                "diagnostic": "550 5.1.1 <user@example.com>: Recipient address rejected: User unknown in virtual mailbox table",
                "email": "user@example.com"
              }
            }
          }
        }
      }
    },
    "/health": {
      "get": {
        "summary": "Cluster liveness check and engine feature introspection",
        "description": "Inspects EmailScore cluster health, active feature flags, supported serialization\nformats, and wire compression algorithms. Public endpoint requiring no authentication;\nideal for infrastructure uptime monitoring, container probes, and smoke tests.",
        "operationId": "check_health",
        "tags": [
          "Engine Telemetry"
        ],
        "security": [],
        "parameters": [],
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "cURL",
            "source": "curl -sS \"https://api.emailscore.io/health\""
          },
          {
            "lang": "Ruby",
            "label": "Ruby",
            "source": "require 'net/http'\nrequire 'uri'\nrequire 'json'\n\nuri = URI('https://api.emailscore.io/health')\nres = Net::HTTP.get_response(uri)\nhealth = JSON.parse(res.body)\n\nputs \"Status: #{health['status']} | Service: #{health['service']}\"\nputs \"Capacity: #{health['capacity']}\"\nputs \"Features: #{health['features'].join(', ')}\""
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import requests\n\nresponse = requests.get(\"https://api.emailscore.io/health\")\nhealth = response.json()\n\nprint(f\"Status: {health['status']} | Service: {health['service']}\")\nprint(f\"Capacity: {health['capacity']}\")\nprint(f\"Features: {', '.join(health['features'])}\")"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "// Engine Health & Metadata Check\nconst response = await fetch('https://api.emailscore.io/health');\nconst health = await response.json();\n\nconsole.log(`Status: ${health.status} | Service: ${health.service}`);\nconsole.log('Capacity:', health.capacity);\nconsole.log('Features:', health.features);"
          },
          {
            "lang": "Go",
            "label": "Go",
            "source": "package main\n\nimport (\n    \"fmt\"\n    \"io\"\n    \"net/http\"\n)\n\nfunc main() {\n    resp, err := http.Get(\"https://api.emailscore.io/health\")\n    if err != nil {\n        panic(err)\n    }\n    defer resp.Body.Close()\n\n    body, _ := io.ReadAll(resp.Body)\n    fmt.Println(string(body))\n}"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.emailscore.io/health\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\n$response = curl_exec($ch);\ncurl_close($ch);\n\n$health = json_decode($response, true);\necho \"Status: \" . $health['status'] . \" | Service: \" . $health['service'] . \"\\n\";\necho \"Capacity: \" . $health['capacity'] . \"\\n\";"
          },
          {
            "lang": "Rust",
            "label": "Rust",
            "source": "use serde_json::Value;\n\n#[tokio::main]\nasync fn main() -> Result<(), Box<dyn std::error::Error>> {\n    let res = reqwest::get(\"https://api.emailscore.io/health\").await?;\n    let health: Value = res.json().await?;\n\n    println!(\"Status: {} | Service: {}\", health[\"status\"], health[\"service\"]);\n    println!(\"Features: {:?}\", health[\"features\"]);\n    Ok(())\n}"
          }
        ],
        "x-code-samples": [
          {
            "lang": "Shell",
            "label": "cURL",
            "source": "curl -sS \"https://api.emailscore.io/health\""
          },
          {
            "lang": "Ruby",
            "label": "Ruby",
            "source": "require 'net/http'\nrequire 'uri'\nrequire 'json'\n\nuri = URI('https://api.emailscore.io/health')\nres = Net::HTTP.get_response(uri)\nhealth = JSON.parse(res.body)\n\nputs \"Status: #{health['status']} | Service: #{health['service']}\"\nputs \"Capacity: #{health['capacity']}\"\nputs \"Features: #{health['features'].join(', ')}\""
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import requests\n\nresponse = requests.get(\"https://api.emailscore.io/health\")\nhealth = response.json()\n\nprint(f\"Status: {health['status']} | Service: {health['service']}\")\nprint(f\"Capacity: {health['capacity']}\")\nprint(f\"Features: {', '.join(health['features'])}\")"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "// Engine Health & Metadata Check\nconst response = await fetch('https://api.emailscore.io/health');\nconst health = await response.json();\n\nconsole.log(`Status: ${health.status} | Service: ${health.service}`);\nconsole.log('Capacity:', health.capacity);\nconsole.log('Features:', health.features);"
          },
          {
            "lang": "Go",
            "label": "Go",
            "source": "package main\n\nimport (\n    \"fmt\"\n    \"io\"\n    \"net/http\"\n)\n\nfunc main() {\n    resp, err := http.Get(\"https://api.emailscore.io/health\")\n    if err != nil {\n        panic(err)\n    }\n    defer resp.Body.Close()\n\n    body, _ := io.ReadAll(resp.Body)\n    fmt.Println(string(body))\n}"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$ch = curl_init(\"https://api.emailscore.io/health\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\n$response = curl_exec($ch);\ncurl_close($ch);\n\n$health = json_decode($response, true);\necho \"Status: \" . $health['status'] . \" | Service: \" . $health['service'] . \"\\n\";\necho \"Capacity: \" . $health['capacity'] . \"\\n\";"
          },
          {
            "lang": "Rust",
            "label": "Rust",
            "source": "use serde_json::Value;\n\n#[tokio::main]\nasync fn main() -> Result<(), Box<dyn std::error::Error>> {\n    let res = reqwest::get(\"https://api.emailscore.io/health\").await?;\n    let health: Value = res.json().await?;\n\n    println!(\"Status: {} | Service: {}\", health[\"status\"], health[\"service\"]);\n    println!(\"Features: {:?}\", health[\"features\"]);\n    Ok(())\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "Engine healthy and operational. Returns cluster telemetry and capability manifest.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "ok",
                        "degraded"
                      ],
                      "description": "Cluster operational health status."
                    },
                    "service": {
                      "type": "string",
                      "description": "Engine runtime identifier and major version."
                    },
                    "domain": {
                      "type": "string",
                      "description": "Canonical API authority domain."
                    },
                    "endpoint": {
                      "type": "string",
                      "description": "Primary email scoring route."
                    },
                    "capacity": {
                      "type": "string",
                      "description": "Verified throughput range per single HTTP connection."
                    },
                    "max_batch_size": {
                      "type": "integer",
                      "description": "Maximum allowable emails in a single bulk batch request."
                    },
                    "supported_formats": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Output format projections supported by the engine."
                    },
                    "sparse_fieldsets": {
                      "type": "string",
                      "description": "Syntax directive for bitmask sparse field projection."
                    },
                    "compression": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Supported transparent stream compression algorithms."
                    },
                    "features": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Active heuristic and database engines in current deployment."
                    }
                  }
                },
                "example": {
                  "status": "ok",
                  "service": "emailscore-v2",
                  "domain": "emailscore.io",
                  "endpoint": "POST /v1/email",
                  "capacity": "1 to 10,000 emails per request",
                  "max_batch_size": 10000,
                  "supported_formats": [
                    "full",
                    "compact"
                  ],
                  "sparse_fieldsets": "supported via ?fields=<dotted_path>",
                  "compression": [
                    "gzip",
                    "br",
                    "zstd",
                    "deflate"
                  ],
                  "features": [
                    "domain_ledger_dynamic_age",
                    "dead_domain_detection",
                    "live_dns_probing",
                    "synthetic_identity_guard",
                    "sqlite_quota_metering"
                  ]
                }
              }
            }
          },
          "503": {
            "description": "Cluster degraded, maintenance mode active, or resolver synchronization in progress.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "status",
                    "error"
                  ],
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "degraded",
                        "maintenance"
                      ],
                      "description": "Cluster health status code."
                    },
                    "error": {
                      "type": "string",
                      "description": "Maintenance or degradation reason."
                    }
                  }
                },
                "example": {
                  "status": "degraded",
                  "error": "Cluster undergoing scheduled DNS resolver sync."
                }
              }
            }
          }
        }
      }
    }
  }
}