{
  "swagger": "2.0",
  "info": {
    "title": "email-validation.org",
    "description": "Validate email addresses one at a time or in bulk.",
    "version": "1.0.0",
    "contact": {
      "name": "email-validation.org support",
      "url": "https://email-validation.org/contact/",
      "email": "support@email-validation.org"
    }
  },
  "host": "api.email-validation.org",
  "basePath": "/",
  "schemes": ["https"],
  "consumes": ["application/json"],
  "produces": ["application/json"],
  "paths": {
    "/v1/validate": {
      "post": {
        "operationId": "validateEmail",
        "summary": "Validate an email address",
        "description": "Checks one address and returns its status, reason and recommended action.",
        "tags": ["Validation"],
        "x-ms-visibility": "important",
        "parameters": [
          {
            "name": "body",
            "in": "body",
            "required": true,
            "description": "The address to check and the options of the check.",
            "x-ms-summary": "Request",
            "schema": {
              "type": "object",
              "properties": {
                "email": {
                  "type": "string",
                  "maxLength": 1024,
                  "description": "The address to check.",
                  "x-ms-summary": "Email Address",
                  "x-ms-visibility": "important"
                },
                "ip_address": {
                  "type": "string",
                  "maxLength": 64,
                  "description": "Optional IPv4 or IPv6 address the person used when they gave you the address (for example at sign-up). Ignored when it is not a valid IP.",
                  "x-ms-summary": "IP Address",
                  "x-ms-visibility": "advanced"
                },
                "timeout": {
                  "type": "integer",
                  "default": 10,
                  "minimum": 5,
                  "maximum": 15,
                  "description": "How many seconds you are willing to wait (5–15). When the check cannot finish in time the result is `unknown` with reason `timeout`, and it is free.",
                  "x-ms-summary": "Timeout (Seconds)",
                  "x-ms-visibility": "advanced"
                },
                "fresh": {
                  "type": "boolean",
                  "default": false,
                  "description": "Set `true` to check the address again even when it was checked in the last 12 months. By default a definite result from such a check can be returned instead; it costs 1 credit like a new check. A definite new result is stored only when no earlier result is; it never replaces or removes a stored one.",
                  "x-ms-summary": "Check Again",
                  "x-ms-visibility": "advanced"
                }
              },
              "required": ["email"],
              "example": {
                "email": "accepted@sandbox.email-validation.org"
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The result. HTTP 200 also covers `unknown` results, which are free.",
            "schema": {
              "type": "object",
              "properties": {
                "email": {
                  "type": "string",
                  "description": "The address as you sent it, without surrounding spaces (test addresses in lower case). For reason `normalized`, the corrected address.",
                  "x-ms-summary": "Email"
                },
                "status": {
                  "type": "string",
                  "enum": ["valid", "invalid", "catch_all", "unknown", "disposable"],
                  "description": "The verdict for the address. `unknown` never costs a credit; every other status costs 1 credit when it comes from a completed check.",
                  "x-ms-summary": "Status"
                },
                "reason": {
                  "type": "string",
                  "enum": [
                    "accepted",
                    "alias",
                    "normalized",
                    "low_engagement",
                    "high_engagement",
                    "trusted_catch_all",
                    "ai_agent",
                    "role_account",
                    "abuse_linked",
                    "suppressed",
                    "trap_pattern",
                    "spamtrap",
                    "complainer",
                    "no_mailbox",
                    "no_inbound_mail",
                    "invalid_syntax",
                    "likely_typo",
                    "no_dns",
                    "mailbox_full",
                    "unroutable",
                    "catch_all",
                    "role_catch_all",
                    "forwarding_domain",
                    "disposable",
                    "server_unavailable",
                    "temporary_error",
                    "greylisted",
                    "anti_spam_block",
                    "timeout",
                    "internal_error"
                  ],
                  "description": "Why the address got its status. Each reason belongs to exactly one status (see `x-reasons-by-status`). Details: https://email-validation.org/docs/statuses/.",
                  "x-ms-summary": "Reason"
                },
                "action": {
                  "type": "string",
                  "enum": ["send", "send_with_caution", "remove", "retry_later"],
                  "description": "What we recommend doing with the address.",
                  "x-ms-summary": "Action"
                },
                "account": {
                  "type": "string",
                  "description": "The part before the `@` of `email`, as written there.",
                  "x-nullable": true,
                  "x-ms-summary": "Account"
                },
                "domain": {
                  "type": "string",
                  "description": "The part after the `@` (international domains in ASCII form).",
                  "x-nullable": true,
                  "x-ms-summary": "Domain"
                },
                "did_you_mean": {
                  "type": "string",
                  "description": "A suggested correction when the address looks like a typo of a common domain.",
                  "x-nullable": true,
                  "x-ms-summary": "Did You Mean"
                },
                "free_email": {
                  "type": "boolean",
                  "description": "True when the domain is a free consumer mailbox service.",
                  "x-nullable": true,
                  "x-ms-summary": "Free Email"
                },
                "role_account": {
                  "type": "boolean",
                  "description": "True when the address belongs to a team or function (such as info@ or sales@) rather than a person: from the check or our own list of such names. Can be true on any status and never changes it.",
                  "x-nullable": true,
                  "x-ms-summary": "Role Account"
                },
                "disposable": {
                  "type": "boolean",
                  "description": "True when the address comes from a throwaway inbox service: from the check or our own list of such domains. A known throwaway address returns the status `disposable`.",
                  "x-nullable": true,
                  "x-ms-summary": "Disposable"
                },
                "catch_all_domain": {
                  "type": "boolean",
                  "description": "True when the domain accepts mail for any address. False when the mail server rejected this mailbox or the domain takes no mail.",
                  "x-nullable": true,
                  "x-ms-summary": "Catch All Domain"
                },
                "mx_found": {
                  "type": "boolean",
                  "description": "True when the domain publishes mail (MX) records; `null` when they were not looked up (for example on a `likely_typo` result).",
                  "x-nullable": true,
                  "x-ms-summary": "MX Found"
                },
                "mx_record": {
                  "type": "string",
                  "description": "The preferred mail server host for the domain.",
                  "x-nullable": true,
                  "x-ms-summary": "MX Record"
                },
                "smtp_provider": {
                  "type": "string",
                  "enum": [
                    "google",
                    "microsoft",
                    "yahoo",
                    "apple",
                    "zoho",
                    "proton",
                    "fastmail",
                    "gmx",
                    "yandex",
                    "mailru",
                    "amazon",
                    "mimecast",
                    "proofpoint",
                    "barracuda",
                    "other"
                  ],
                  "description": "The mail provider that hosts the domain's mailboxes: `google` (Google), `microsoft` (Microsoft), `yahoo` (Yahoo), `apple` (Apple iCloud), `zoho` (Zoho), `proton` (Proton), `fastmail` (Fastmail), `gmx` (GMX / Web.de), `yandex` (Yandex), `mailru` (Mail.ru), `amazon` (Amazon), `mimecast` (Mimecast), `proofpoint` (Proofpoint), `barracuda` (Barracuda), `other` (Other).",
                  "x-nullable": true,
                  "x-ms-summary": "SMTP Provider"
                },
                "domain_age_days": {
                  "type": "integer",
                  "minimum": 0,
                  "description": "Age of the domain registration in days, when known.",
                  "x-nullable": true,
                  "x-ms-summary": "Domain Age Days"
                },
                "processed_at": {
                  "type": "string",
                  "format": "date-time",
                  "description": "When this result was produced (UTC). A result reused from a check of the same address can come from a check made up to 12 months earlier; send `fresh=true` for a new check.",
                  "x-ms-summary": "Processed At"
                },
                "credits_used": {
                  "type": "integer",
                  "enum": [0, 1],
                  "description": "1 when this result cost a credit. Results with status `unknown`, answers to malformed addresses and sandbox addresses are free. It is provisional until your usage shows it; rarely, it turns out free.",
                  "x-ms-summary": "Credits Used"
                },
                "request_id": {
                  "type": "string",
                  "pattern": "^req_[0-9A-Za-z]{22}$",
                  "description": "Our id for this request. Keep it in your logs, and quote it in a billing or legal dispute sent to legal@email-validation.org, which a person reads; the AI support assistant cannot look requests up.",
                  "x-ms-summary": "Request ID"
                }
              },
              "required": [
                "email",
                "status",
                "reason",
                "action",
                "account",
                "domain",
                "did_you_mean",
                "free_email",
                "role_account",
                "disposable",
                "catch_all_domain",
                "mx_found",
                "mx_record",
                "smtp_provider",
                "domain_age_days",
                "processed_at",
                "credits_used",
                "request_id"
              ],
              "description": "The result of one check. Fields always appear in this order; values are `null` when they do not apply or are not known."
            },
            "examples": {
              "application/json": {
                "email": "accepted@sandbox.email-validation.org",
                "status": "valid",
                "reason": "accepted",
                "action": "send",
                "account": "accepted",
                "domain": "sandbox.email-validation.org",
                "did_you_mean": null,
                "free_email": false,
                "role_account": false,
                "disposable": false,
                "catch_all_domain": false,
                "mx_found": true,
                "mx_record": "mx.sandbox.email-validation.org",
                "smtp_provider": "other",
                "domain_age_days": 3650,
                "processed_at": "2026-10-20T09:30:00.000Z",
                "credits_used": 0,
                "request_id": "req_7Hq2LmX9cV4bN8tR1zK6wD"
              }
            }
          }
        }
      }
    },
    "/v1/credits": {
      "get": {
        "operationId": "getCredits",
        "summary": "Get your credit balance",
        "description": "Returns the spendable balance, any debt, credits still being applied, and the credit lots with their expiry dates. Needs the `account:read` scope.",
        "tags": ["Account"],
        "x-ms-visibility": "important",
        "responses": {
          "200": {
            "description": "Your credits.",
            "schema": {
              "type": "object",
              "properties": {
                "balance": {
                  "type": "integer",
                  "description": "Credits you can spend now.",
                  "x-ms-summary": "Balance"
                },
                "debt": {
                  "type": "integer",
                  "minimum": 0,
                  "description": "Credits owed after a refund or reversal; new credits pay this off first.",
                  "x-ms-summary": "Debt"
                },
                "pending": {
                  "type": "integer",
                  "minimum": 0,
                  "description": "Credits granted moments ago that are still being applied. They become spendable shortly.",
                  "x-ms-summary": "Pending"
                },
                "lots": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "remaining": {
                        "type": "integer",
                        "description": "Credits left in this lot.",
                        "x-ms-summary": "Remaining"
                      },
                      "expires_at": {
                        "type": "string",
                        "format": "date-time",
                        "description": "When the credits in this lot expire.",
                        "x-ms-summary": "Expires At"
                      }
                    },
                    "required": ["remaining", "expires_at"]
                  },
                  "description": "Credit lots with credits left, soonest-expiring first. Credits are spent in this order.",
                  "x-ms-summary": "Lots"
                }
              },
              "required": ["balance", "debt", "pending", "lots"]
            },
            "examples": {
              "application/json": {
                "balance": 24350,
                "debt": 0,
                "pending": 0,
                "lots": [
                  {
                    "remaining": 850,
                    "expires_at": "2027-03-14T12:00:00.000Z"
                  },
                  {
                    "remaining": 23500,
                    "expires_at": "2028-09-30T08:15:00.000Z"
                  }
                ]
              }
            }
          }
        }
      }
    },
    "/v1/usage": {
      "get": {
        "operationId": "getUsage",
        "summary": "Get credit usage by day or by key",
        "description": "Credit usage for any window within the last 90 days. Daily credit totals come from the credit ledger and are exact; the split by status (API, MCP, dashboard and bulk results) is compiled from request records and is approximate (it can lag by up to an hour). `totals` are always the whole account; with `group_by=key` the items cover only credits spent through an API key. Needs the `account:read` scope.",
        "tags": ["Account"],
        "x-ms-visibility": "advanced",
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "type": "string",
            "format": "date",
            "description": "First day (UTC, `YYYY-MM-DD`), no earlier than 89 days before today: usage covers the last 90 days. Defaults to the start of the 90-day range that ends on `to`.",
            "x-ms-summary": "From Date",
            "x-ms-visibility": "advanced"
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "type": "string",
            "format": "date",
            "description": "Last day (UTC). Defaults to today. The whole window must lie within the last 90 days (today included); an earlier day is a `400`.",
            "x-ms-summary": "To Date",
            "x-ms-visibility": "advanced"
          },
          {
            "name": "group_by",
            "in": "query",
            "required": false,
            "type": "string",
            "enum": ["day", "key"],
            "default": "day",
            "description": "Group the usage by day or by API key.",
            "x-ms-summary": "Group By",
            "x-ms-visibility": "advanced"
          }
        ],
        "responses": {
          "200": {
            "description": "Usage for the range.",
            "schema": {
              "type": "object",
              "properties": {
                "from": {
                  "type": "string",
                  "format": "date",
                  "description": "First day included (UTC).",
                  "x-ms-summary": "From"
                },
                "to": {
                  "type": "string",
                  "format": "date",
                  "description": "Last day included (UTC).",
                  "x-ms-summary": "To"
                },
                "group_by": {
                  "type": "string",
                  "enum": ["day", "key"],
                  "x-ms-summary": "Group By"
                },
                "totals": {
                  "type": "object",
                  "properties": {
                    "credits_used": {
                      "type": "integer",
                      "minimum": 0,
                      "description": "Credits used in the range, from the credit ledger (exact).",
                      "x-ms-summary": "Credits Used"
                    },
                    "by_status": {
                      "type": "object",
                      "properties": {
                        "valid": {
                          "type": "integer",
                          "minimum": 0,
                          "x-ms-summary": "Valid"
                        },
                        "invalid": {
                          "type": "integer",
                          "minimum": 0,
                          "x-ms-summary": "Invalid"
                        },
                        "catch_all": {
                          "type": "integer",
                          "minimum": 0,
                          "x-ms-summary": "Catch All"
                        },
                        "unknown": {
                          "type": "integer",
                          "minimum": 0,
                          "x-ms-summary": "Unknown"
                        },
                        "disposable": {
                          "type": "integer",
                          "minimum": 0,
                          "x-ms-summary": "Disposable"
                        }
                      },
                      "required": ["valid", "invalid", "catch_all", "unknown", "disposable"],
                      "description": "Results by status (approximate; may lag by up to an hour).",
                      "x-ms-summary": "By Status"
                    }
                  },
                  "required": ["credits_used", "by_status"],
                  "description": "Totals of the whole account for the range, whatever `group_by`: API, MCP, dashboard and bulk usage. With `group_by=key` they can be larger than the sum of the items, because bulk jobs and dashboard checks are not tied to a key.",
                  "x-ms-summary": "Totals"
                },
                "items": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "date": {
                        "type": "string",
                        "format": "date",
                        "x-ms-summary": "Date"
                      },
                      "credits_used": {
                        "type": "integer",
                        "minimum": 0,
                        "description": "Credits used that day, from the credit ledger (exact).",
                        "x-ms-summary": "Credits Used"
                      },
                      "by_status": {
                        "type": "object",
                        "properties": {
                          "valid": {
                            "type": "integer",
                            "minimum": 0,
                            "x-ms-summary": "Valid"
                          },
                          "invalid": {
                            "type": "integer",
                            "minimum": 0,
                            "x-ms-summary": "Invalid"
                          },
                          "catch_all": {
                            "type": "integer",
                            "minimum": 0,
                            "x-ms-summary": "Catch All"
                          },
                          "unknown": {
                            "type": "integer",
                            "minimum": 0,
                            "x-ms-summary": "Unknown"
                          },
                          "disposable": {
                            "type": "integer",
                            "minimum": 0,
                            "x-ms-summary": "Disposable"
                          }
                        },
                        "required": ["valid", "invalid", "catch_all", "unknown", "disposable"],
                        "description": "Results by status (approximate; may lag by up to an hour).",
                        "x-ms-summary": "By Status"
                      },
                      "key_id": {
                        "type": "string",
                        "pattern": "^key_[0-9A-Za-z]{22}$",
                        "description": "API key id (never the key itself).",
                        "x-ms-summary": "Key ID"
                      },
                      "name": {
                        "type": "string",
                        "description": "The name you gave the key (null for a deleted key).",
                        "x-nullable": true,
                        "x-ms-summary": "Name"
                      },
                      "last4": {
                        "type": "string",
                        "description": "Last 4 characters of the key, as shown in the dashboard.",
                        "x-nullable": true,
                        "x-ms-summary": "Last4"
                      }
                    },
                    "required": ["credits_used"]
                  },
                  "description": "One item per day (`group_by=day`) or per API key (`group_by=key`).",
                  "x-ms-summary": "Items"
                }
              },
              "required": ["from", "to", "group_by", "totals", "items"]
            },
            "examples": {
              "application/json": {
                "from": "2026-10-19",
                "to": "2026-10-20",
                "group_by": "day",
                "totals": {
                  "credits_used": 1212,
                  "by_status": {
                    "valid": 1040,
                    "invalid": 121,
                    "catch_all": 42,
                    "unknown": 31,
                    "disposable": 9
                  }
                },
                "items": [
                  {
                    "date": "2026-10-19",
                    "credits_used": 640,
                    "by_status": {
                      "valid": 552,
                      "invalid": 61,
                      "catch_all": 22,
                      "unknown": 17,
                      "disposable": 5
                    }
                  },
                  {
                    "date": "2026-10-20",
                    "credits_used": 572,
                    "by_status": {
                      "valid": 488,
                      "invalid": 60,
                      "catch_all": 20,
                      "unknown": 14,
                      "disposable": 4
                    }
                  }
                ]
              }
            }
          }
        }
      }
    },
    "/v1/bulk": {
      "post": {
        "operationId": "createBulkJob",
        "summary": "Create a bulk job",
        "description": "Creates a bulk job from a list of addresses sent as JSON: up to 100,000 addresses, at most 4 MB (larger lists and CSV files: upload them in the dashboard). The job starts in `analyzing`: we read the file, remove duplicates and answer malformed addresses for free. Then it either starts on its own (`start=true`, the default) or waits in `ready` until you start it. Credits are held for every unique address that needs a check when the job starts, and anything not used is returned when it ends. Files and results are deleted 30 days after upload (results of a list that finishes in its last day are kept for 7 days after it finishes). Needs a key with the `bulk` scope. Quotas: an account without a purchase may have at most 2 lists that are `analyzing` or `ready` (jobs that start on their own count while they are analyzed); another upload is a `409 conflict` until one starts or is canceled. Stored lists may take up to 2 GB without a purchase and 20 GB with one; an upload over the quota is a `413 payload_too_large`. Open this action's Settings and set Retry policy to None and Asynchronous pattern to Off: the API cannot tell a re-sent create from a new list, so a retry can create, and charge for, the same list twice (the 202 answer is already the job; there is nothing to poll). If a create fails with a 5xx error or a timeout, check the bulk page of the dashboard (https://email-validation.org/app/bulk/, which lists API jobs too) before running it again.",
        "tags": ["Bulk jobs"],
        "x-ms-visibility": "important",
        "parameters": [
          {
            "name": "start",
            "in": "query",
            "required": false,
            "type": "boolean",
            "default": true,
            "description": "Start checking as soon as the file has been analyzed. Set `false` to review the cost first and call the start endpoint later.",
            "x-ms-summary": "Start Automatically",
            "x-ms-visibility": "important"
          },
          {
            "name": "webhook_endpoint_id",
            "in": "query",
            "required": false,
            "type": "string",
            "maxLength": 64,
            "description": "Id of a webhook endpoint registered in the dashboard. We notify it when the job finishes, even if it did not subscribe to `bulk.completed` / `bulk.failed`.",
            "x-ms-summary": "Webhook Endpoint ID",
            "x-ms-visibility": "advanced"
          },
          {
            "name": "body",
            "in": "body",
            "required": true,
            "description": "The list of addresses to check, as JSON.",
            "x-ms-summary": "Addresses",
            "schema": {
              "type": "object",
              "properties": {
                "emails": {
                  "type": "array",
                  "minItems": 1,
                  "maxItems": 100000,
                  "items": {
                    "type": "string",
                    "maxLength": 1024
                  },
                  "description": "Up to 100,000 addresses; the JSON body is at most 4 MB (send larger lists as CSV).",
                  "x-ms-summary": "Email Addresses",
                  "x-ms-visibility": "important"
                }
              },
              "required": ["emails"],
              "example": {
                "emails": ["accepted@sandbox.email-validation.org", "catch_all@sandbox.email-validation.org"]
              }
            }
          }
        ],
        "responses": {
          "202": {
            "description": "Job created and being analyzed.",
            "schema": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "pattern": "^job_[0-9A-Za-z]{22}$",
                  "description": "Bulk job id.",
                  "x-ms-summary": "ID"
                },
                "status": {
                  "type": "string",
                  "enum": [
                    "analyzing",
                    "ready",
                    "queued",
                    "running",
                    "cancelling",
                    "finalizing",
                    "completed",
                    "failed",
                    "cancelled",
                    "expired"
                  ],
                  "x-ms-summary": "Status"
                },
                "filename": {
                  "type": "string",
                  "x-nullable": true,
                  "x-ms-summary": "Filename"
                },
                "total_rows": {
                  "type": "integer",
                  "description": "Data rows in the file (header excluded).",
                  "x-nullable": true,
                  "x-ms-summary": "Total Rows"
                },
                "unique_emails": {
                  "type": "integer",
                  "description": "Distinct addresses after normalization.",
                  "x-nullable": true,
                  "x-ms-summary": "Unique Emails"
                },
                "duplicates": {
                  "type": "integer",
                  "description": "Rows that repeat an address seen earlier in the file.",
                  "x-nullable": true,
                  "x-ms-summary": "Duplicates"
                },
                "syntax_invalid": {
                  "type": "integer",
                  "description": "Addresses that are not well formed (answered for free).",
                  "x-nullable": true,
                  "x-ms-summary": "Syntax Invalid"
                },
                "local_answered": {
                  "type": "integer",
                  "description": "Addresses answered without a mail-server check (malformed and sandbox addresses), all free.",
                  "x-nullable": true,
                  "x-ms-summary": "Local Answered"
                },
                "processed": {
                  "type": "integer",
                  "minimum": 0,
                  "description": "Unique addresses with a final result so far.",
                  "x-ms-summary": "Processed"
                },
                "credits_reserved": {
                  "type": "integer",
                  "minimum": 0,
                  "description": "Credits held when the job started: one per unique address that needs a check.",
                  "x-ms-summary": "Credits Reserved"
                },
                "credits_charged": {
                  "type": "integer",
                  "minimum": 0,
                  "description": "Credits actually used. When the job ends, the difference to `credits_reserved` is returned.",
                  "x-ms-summary": "Credits Charged"
                },
                "counts": {
                  "type": "object",
                  "properties": {
                    "valid": {
                      "type": "integer",
                      "minimum": 0,
                      "x-ms-summary": "Valid"
                    },
                    "invalid": {
                      "type": "integer",
                      "minimum": 0,
                      "x-ms-summary": "Invalid"
                    },
                    "catch_all": {
                      "type": "integer",
                      "minimum": 0,
                      "x-ms-summary": "Catch All"
                    },
                    "unknown": {
                      "type": "integer",
                      "minimum": 0,
                      "x-ms-summary": "Unknown"
                    },
                    "disposable": {
                      "type": "integer",
                      "minimum": 0,
                      "x-ms-summary": "Disposable"
                    }
                  },
                  "description": "Results so far by status.",
                  "x-ms-summary": "Counts"
                },
                "error_code": {
                  "type": "string",
                  "enum": [
                    "invalid_csv",
                    "too_many_rows",
                    "empty_file",
                    "email_column_not_found",
                    "upload_missing",
                    "pipeline_mismatch",
                    "missing_results",
                    "internal_error",
                    "insufficient_credits",
                    "upstream_capacity",
                    "account_suspended",
                    "billing_hold",
                    "invalid_key",
                    "forbidden_scope",
                    "key_daily_cap",
                    "upload_expired"
                  ],
                  "description": "Why a job failed or is waiting in `ready`, for example `insufficient_credits` (the job stays `ready`) or `invalid_csv`. Every value: https://email-validation.org/docs/api/bulk/#errors.",
                  "x-nullable": true,
                  "x-ms-summary": "Error Code"
                },
                "webhook_endpoint_id": {
                  "type": "string",
                  "description": "Registered webhook endpoint notified about this job.",
                  "x-nullable": true,
                  "x-ms-summary": "Webhook Endpoint ID"
                },
                "created_at": {
                  "type": "string",
                  "format": "date-time",
                  "description": "When the job was created.",
                  "x-ms-summary": "Created At"
                },
                "started_at": {
                  "type": "string",
                  "format": "date-time",
                  "x-nullable": true,
                  "x-ms-summary": "Started At"
                },
                "finished_at": {
                  "type": "string",
                  "format": "date-time",
                  "x-nullable": true,
                  "x-ms-summary": "Finished At"
                },
                "expires_at": {
                  "type": "string",
                  "format": "date-time",
                  "description": "When the uploaded file and the results are deleted (30 days after upload; results of a list that finishes in its last day are kept for 7 days after it finishes).",
                  "x-ms-summary": "Expires At"
                }
              },
              "required": [
                "id",
                "status",
                "filename",
                "total_rows",
                "unique_emails",
                "duplicates",
                "syntax_invalid",
                "local_answered",
                "processed",
                "credits_reserved",
                "credits_charged",
                "counts",
                "error_code",
                "webhook_endpoint_id",
                "created_at",
                "started_at",
                "finished_at",
                "expires_at"
              ],
              "description": "A bulk job. Counters are `null` until the file has been read (`analyzing`)."
            },
            "examples": {
              "application/json": {
                "id": "job_3Fv8QpL2xM7nC1rT9kW4yB",
                "status": "analyzing",
                "filename": "newsletter-2026-11.csv",
                "total_rows": null,
                "unique_emails": null,
                "duplicates": null,
                "syntax_invalid": null,
                "local_answered": null,
                "processed": 0,
                "credits_reserved": 0,
                "credits_charged": 0,
                "counts": {},
                "error_code": null,
                "webhook_endpoint_id": null,
                "created_at": "2026-10-20T09:30:00.000Z",
                "started_at": null,
                "finished_at": null,
                "expires_at": "2026-11-19T09:30:00.000Z"
              }
            }
          }
        }
      }
    },
    "/v1/bulk/{id}": {
      "get": {
        "operationId": "getBulkJob",
        "summary": "Get a bulk job",
        "description": "Returns the job with its progress and counts. Poll every few seconds, or use a webhook.",
        "tags": ["Bulk jobs"],
        "x-ms-visibility": "important",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "type": "string",
            "pattern": "^job_[0-9A-Za-z]{22}$",
            "description": "Bulk job id.",
            "x-ms-summary": "Job ID",
            "x-ms-visibility": "important",
            "x-ms-url-encoding": "single"
          }
        ],
        "responses": {
          "200": {
            "description": "The job.",
            "schema": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "pattern": "^job_[0-9A-Za-z]{22}$",
                  "description": "Bulk job id.",
                  "x-ms-summary": "ID"
                },
                "status": {
                  "type": "string",
                  "enum": [
                    "analyzing",
                    "ready",
                    "queued",
                    "running",
                    "cancelling",
                    "finalizing",
                    "completed",
                    "failed",
                    "cancelled",
                    "expired"
                  ],
                  "x-ms-summary": "Status"
                },
                "filename": {
                  "type": "string",
                  "x-nullable": true,
                  "x-ms-summary": "Filename"
                },
                "total_rows": {
                  "type": "integer",
                  "description": "Data rows in the file (header excluded).",
                  "x-nullable": true,
                  "x-ms-summary": "Total Rows"
                },
                "unique_emails": {
                  "type": "integer",
                  "description": "Distinct addresses after normalization.",
                  "x-nullable": true,
                  "x-ms-summary": "Unique Emails"
                },
                "duplicates": {
                  "type": "integer",
                  "description": "Rows that repeat an address seen earlier in the file.",
                  "x-nullable": true,
                  "x-ms-summary": "Duplicates"
                },
                "syntax_invalid": {
                  "type": "integer",
                  "description": "Addresses that are not well formed (answered for free).",
                  "x-nullable": true,
                  "x-ms-summary": "Syntax Invalid"
                },
                "local_answered": {
                  "type": "integer",
                  "description": "Addresses answered without a mail-server check (malformed and sandbox addresses), all free.",
                  "x-nullable": true,
                  "x-ms-summary": "Local Answered"
                },
                "processed": {
                  "type": "integer",
                  "minimum": 0,
                  "description": "Unique addresses with a final result so far.",
                  "x-ms-summary": "Processed"
                },
                "credits_reserved": {
                  "type": "integer",
                  "minimum": 0,
                  "description": "Credits held when the job started: one per unique address that needs a check.",
                  "x-ms-summary": "Credits Reserved"
                },
                "credits_charged": {
                  "type": "integer",
                  "minimum": 0,
                  "description": "Credits actually used. When the job ends, the difference to `credits_reserved` is returned.",
                  "x-ms-summary": "Credits Charged"
                },
                "counts": {
                  "type": "object",
                  "properties": {
                    "valid": {
                      "type": "integer",
                      "minimum": 0,
                      "x-ms-summary": "Valid"
                    },
                    "invalid": {
                      "type": "integer",
                      "minimum": 0,
                      "x-ms-summary": "Invalid"
                    },
                    "catch_all": {
                      "type": "integer",
                      "minimum": 0,
                      "x-ms-summary": "Catch All"
                    },
                    "unknown": {
                      "type": "integer",
                      "minimum": 0,
                      "x-ms-summary": "Unknown"
                    },
                    "disposable": {
                      "type": "integer",
                      "minimum": 0,
                      "x-ms-summary": "Disposable"
                    }
                  },
                  "description": "Results so far by status.",
                  "x-ms-summary": "Counts"
                },
                "error_code": {
                  "type": "string",
                  "enum": [
                    "invalid_csv",
                    "too_many_rows",
                    "empty_file",
                    "email_column_not_found",
                    "upload_missing",
                    "pipeline_mismatch",
                    "missing_results",
                    "internal_error",
                    "insufficient_credits",
                    "upstream_capacity",
                    "account_suspended",
                    "billing_hold",
                    "invalid_key",
                    "forbidden_scope",
                    "key_daily_cap",
                    "upload_expired"
                  ],
                  "description": "Why a job failed or is waiting in `ready`, for example `insufficient_credits` (the job stays `ready`) or `invalid_csv`. Every value: https://email-validation.org/docs/api/bulk/#errors.",
                  "x-nullable": true,
                  "x-ms-summary": "Error Code"
                },
                "webhook_endpoint_id": {
                  "type": "string",
                  "description": "Registered webhook endpoint notified about this job.",
                  "x-nullable": true,
                  "x-ms-summary": "Webhook Endpoint ID"
                },
                "created_at": {
                  "type": "string",
                  "format": "date-time",
                  "description": "When the job was created.",
                  "x-ms-summary": "Created At"
                },
                "started_at": {
                  "type": "string",
                  "format": "date-time",
                  "x-nullable": true,
                  "x-ms-summary": "Started At"
                },
                "finished_at": {
                  "type": "string",
                  "format": "date-time",
                  "x-nullable": true,
                  "x-ms-summary": "Finished At"
                },
                "expires_at": {
                  "type": "string",
                  "format": "date-time",
                  "description": "When the uploaded file and the results are deleted (30 days after upload; results of a list that finishes in its last day are kept for 7 days after it finishes).",
                  "x-ms-summary": "Expires At"
                }
              },
              "required": [
                "id",
                "status",
                "filename",
                "total_rows",
                "unique_emails",
                "duplicates",
                "syntax_invalid",
                "local_answered",
                "processed",
                "credits_reserved",
                "credits_charged",
                "counts",
                "error_code",
                "webhook_endpoint_id",
                "created_at",
                "started_at",
                "finished_at",
                "expires_at"
              ],
              "description": "A bulk job. Counters are `null` until the file has been read (`analyzing`)."
            },
            "examples": {
              "application/json": {
                "id": "job_3Fv8QpL2xM7nC1rT9kW4yB",
                "status": "completed",
                "filename": "newsletter-2026-11.csv",
                "total_rows": 12480,
                "unique_emails": 12102,
                "duplicates": 378,
                "syntax_invalid": 41,
                "local_answered": 41,
                "processed": 12102,
                "credits_reserved": 12061,
                "credits_charged": 11874,
                "counts": {
                  "valid": 10447,
                  "invalid": 977,
                  "catch_all": 401,
                  "unknown": 187,
                  "disposable": 90
                },
                "error_code": null,
                "webhook_endpoint_id": "whk_9Lp4XcV2nB7mQ1tR6zK3wF",
                "created_at": "2026-10-20T09:30:00.000Z",
                "started_at": "2026-10-20T09:30:41.000Z",
                "finished_at": "2026-10-20T09:52:07.000Z",
                "expires_at": "2026-11-19T09:30:00.000Z"
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "cancelBulkJob",
        "summary": "Cancel a bulk job",
        "description": "Cancels the job. Work in flight finishes (`cancelling`), then the job becomes `cancelled`, unused credits are returned and its files are deleted. Canceling a finished job is a `conflict`.",
        "tags": ["Bulk jobs"],
        "x-ms-visibility": "advanced",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "type": "string",
            "pattern": "^job_[0-9A-Za-z]{22}$",
            "description": "Bulk job id.",
            "x-ms-summary": "Job ID",
            "x-ms-visibility": "important",
            "x-ms-url-encoding": "single"
          }
        ],
        "responses": {
          "200": {
            "description": "The job after the cancel request.",
            "schema": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "pattern": "^job_[0-9A-Za-z]{22}$",
                  "description": "Bulk job id.",
                  "x-ms-summary": "ID"
                },
                "status": {
                  "type": "string",
                  "enum": [
                    "analyzing",
                    "ready",
                    "queued",
                    "running",
                    "cancelling",
                    "finalizing",
                    "completed",
                    "failed",
                    "cancelled",
                    "expired"
                  ],
                  "x-ms-summary": "Status"
                },
                "filename": {
                  "type": "string",
                  "x-nullable": true,
                  "x-ms-summary": "Filename"
                },
                "total_rows": {
                  "type": "integer",
                  "description": "Data rows in the file (header excluded).",
                  "x-nullable": true,
                  "x-ms-summary": "Total Rows"
                },
                "unique_emails": {
                  "type": "integer",
                  "description": "Distinct addresses after normalization.",
                  "x-nullable": true,
                  "x-ms-summary": "Unique Emails"
                },
                "duplicates": {
                  "type": "integer",
                  "description": "Rows that repeat an address seen earlier in the file.",
                  "x-nullable": true,
                  "x-ms-summary": "Duplicates"
                },
                "syntax_invalid": {
                  "type": "integer",
                  "description": "Addresses that are not well formed (answered for free).",
                  "x-nullable": true,
                  "x-ms-summary": "Syntax Invalid"
                },
                "local_answered": {
                  "type": "integer",
                  "description": "Addresses answered without a mail-server check (malformed and sandbox addresses), all free.",
                  "x-nullable": true,
                  "x-ms-summary": "Local Answered"
                },
                "processed": {
                  "type": "integer",
                  "minimum": 0,
                  "description": "Unique addresses with a final result so far.",
                  "x-ms-summary": "Processed"
                },
                "credits_reserved": {
                  "type": "integer",
                  "minimum": 0,
                  "description": "Credits held when the job started: one per unique address that needs a check.",
                  "x-ms-summary": "Credits Reserved"
                },
                "credits_charged": {
                  "type": "integer",
                  "minimum": 0,
                  "description": "Credits actually used. When the job ends, the difference to `credits_reserved` is returned.",
                  "x-ms-summary": "Credits Charged"
                },
                "counts": {
                  "type": "object",
                  "properties": {
                    "valid": {
                      "type": "integer",
                      "minimum": 0,
                      "x-ms-summary": "Valid"
                    },
                    "invalid": {
                      "type": "integer",
                      "minimum": 0,
                      "x-ms-summary": "Invalid"
                    },
                    "catch_all": {
                      "type": "integer",
                      "minimum": 0,
                      "x-ms-summary": "Catch All"
                    },
                    "unknown": {
                      "type": "integer",
                      "minimum": 0,
                      "x-ms-summary": "Unknown"
                    },
                    "disposable": {
                      "type": "integer",
                      "minimum": 0,
                      "x-ms-summary": "Disposable"
                    }
                  },
                  "description": "Results so far by status.",
                  "x-ms-summary": "Counts"
                },
                "error_code": {
                  "type": "string",
                  "enum": [
                    "invalid_csv",
                    "too_many_rows",
                    "empty_file",
                    "email_column_not_found",
                    "upload_missing",
                    "pipeline_mismatch",
                    "missing_results",
                    "internal_error",
                    "insufficient_credits",
                    "upstream_capacity",
                    "account_suspended",
                    "billing_hold",
                    "invalid_key",
                    "forbidden_scope",
                    "key_daily_cap",
                    "upload_expired"
                  ],
                  "description": "Why a job failed or is waiting in `ready`, for example `insufficient_credits` (the job stays `ready`) or `invalid_csv`. Every value: https://email-validation.org/docs/api/bulk/#errors.",
                  "x-nullable": true,
                  "x-ms-summary": "Error Code"
                },
                "webhook_endpoint_id": {
                  "type": "string",
                  "description": "Registered webhook endpoint notified about this job.",
                  "x-nullable": true,
                  "x-ms-summary": "Webhook Endpoint ID"
                },
                "created_at": {
                  "type": "string",
                  "format": "date-time",
                  "description": "When the job was created.",
                  "x-ms-summary": "Created At"
                },
                "started_at": {
                  "type": "string",
                  "format": "date-time",
                  "x-nullable": true,
                  "x-ms-summary": "Started At"
                },
                "finished_at": {
                  "type": "string",
                  "format": "date-time",
                  "x-nullable": true,
                  "x-ms-summary": "Finished At"
                },
                "expires_at": {
                  "type": "string",
                  "format": "date-time",
                  "description": "When the uploaded file and the results are deleted (30 days after upload; results of a list that finishes in its last day are kept for 7 days after it finishes).",
                  "x-ms-summary": "Expires At"
                }
              },
              "required": [
                "id",
                "status",
                "filename",
                "total_rows",
                "unique_emails",
                "duplicates",
                "syntax_invalid",
                "local_answered",
                "processed",
                "credits_reserved",
                "credits_charged",
                "counts",
                "error_code",
                "webhook_endpoint_id",
                "created_at",
                "started_at",
                "finished_at",
                "expires_at"
              ],
              "description": "A bulk job. Counters are `null` until the file has been read (`analyzing`)."
            },
            "examples": {
              "application/json": {
                "id": "job_3Fv8QpL2xM7nC1rT9kW4yB",
                "status": "cancelling",
                "filename": "newsletter-2026-11.csv",
                "total_rows": 12480,
                "unique_emails": 12102,
                "duplicates": 378,
                "syntax_invalid": 41,
                "local_answered": 41,
                "processed": 4120,
                "credits_reserved": 12061,
                "credits_charged": 4031,
                "counts": {
                  "valid": 3570,
                  "invalid": 331,
                  "catch_all": 110,
                  "unknown": 89,
                  "disposable": 20
                },
                "error_code": null,
                "webhook_endpoint_id": "whk_9Lp4XcV2nB7mQ1tR6zK3wF",
                "created_at": "2026-10-20T09:30:00.000Z",
                "started_at": "2026-10-20T09:30:41.000Z",
                "finished_at": null,
                "expires_at": "2026-11-19T09:30:00.000Z"
              }
            }
          }
        }
      }
    },
    "/v1/bulk/{id}/start": {
      "post": {
        "operationId": "startBulkJob",
        "summary": "Start a bulk job",
        "description": "Starts a job that is `ready`. Credits for every unique address that needs a check are held now and count toward the daily credit cap of the API key that starts it. Answers `insufficient_credits` when the balance is too low and `key_daily_cap` (429) when the job would pass the key's daily cap (the job stays `ready` either way). Safe to run again: starting a job that already started returns it and never holds credits twice.",
        "tags": ["Bulk jobs"],
        "x-ms-visibility": "important",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "type": "string",
            "pattern": "^job_[0-9A-Za-z]{22}$",
            "description": "Bulk job id.",
            "x-ms-summary": "Job ID",
            "x-ms-visibility": "important",
            "x-ms-url-encoding": "single"
          }
        ],
        "responses": {
          "200": {
            "description": "The started job.",
            "schema": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "pattern": "^job_[0-9A-Za-z]{22}$",
                  "description": "Bulk job id.",
                  "x-ms-summary": "ID"
                },
                "status": {
                  "type": "string",
                  "enum": [
                    "analyzing",
                    "ready",
                    "queued",
                    "running",
                    "cancelling",
                    "finalizing",
                    "completed",
                    "failed",
                    "cancelled",
                    "expired"
                  ],
                  "x-ms-summary": "Status"
                },
                "filename": {
                  "type": "string",
                  "x-nullable": true,
                  "x-ms-summary": "Filename"
                },
                "total_rows": {
                  "type": "integer",
                  "description": "Data rows in the file (header excluded).",
                  "x-nullable": true,
                  "x-ms-summary": "Total Rows"
                },
                "unique_emails": {
                  "type": "integer",
                  "description": "Distinct addresses after normalization.",
                  "x-nullable": true,
                  "x-ms-summary": "Unique Emails"
                },
                "duplicates": {
                  "type": "integer",
                  "description": "Rows that repeat an address seen earlier in the file.",
                  "x-nullable": true,
                  "x-ms-summary": "Duplicates"
                },
                "syntax_invalid": {
                  "type": "integer",
                  "description": "Addresses that are not well formed (answered for free).",
                  "x-nullable": true,
                  "x-ms-summary": "Syntax Invalid"
                },
                "local_answered": {
                  "type": "integer",
                  "description": "Addresses answered without a mail-server check (malformed and sandbox addresses), all free.",
                  "x-nullable": true,
                  "x-ms-summary": "Local Answered"
                },
                "processed": {
                  "type": "integer",
                  "minimum": 0,
                  "description": "Unique addresses with a final result so far.",
                  "x-ms-summary": "Processed"
                },
                "credits_reserved": {
                  "type": "integer",
                  "minimum": 0,
                  "description": "Credits held when the job started: one per unique address that needs a check.",
                  "x-ms-summary": "Credits Reserved"
                },
                "credits_charged": {
                  "type": "integer",
                  "minimum": 0,
                  "description": "Credits actually used. When the job ends, the difference to `credits_reserved` is returned.",
                  "x-ms-summary": "Credits Charged"
                },
                "counts": {
                  "type": "object",
                  "properties": {
                    "valid": {
                      "type": "integer",
                      "minimum": 0,
                      "x-ms-summary": "Valid"
                    },
                    "invalid": {
                      "type": "integer",
                      "minimum": 0,
                      "x-ms-summary": "Invalid"
                    },
                    "catch_all": {
                      "type": "integer",
                      "minimum": 0,
                      "x-ms-summary": "Catch All"
                    },
                    "unknown": {
                      "type": "integer",
                      "minimum": 0,
                      "x-ms-summary": "Unknown"
                    },
                    "disposable": {
                      "type": "integer",
                      "minimum": 0,
                      "x-ms-summary": "Disposable"
                    }
                  },
                  "description": "Results so far by status.",
                  "x-ms-summary": "Counts"
                },
                "error_code": {
                  "type": "string",
                  "enum": [
                    "invalid_csv",
                    "too_many_rows",
                    "empty_file",
                    "email_column_not_found",
                    "upload_missing",
                    "pipeline_mismatch",
                    "missing_results",
                    "internal_error",
                    "insufficient_credits",
                    "upstream_capacity",
                    "account_suspended",
                    "billing_hold",
                    "invalid_key",
                    "forbidden_scope",
                    "key_daily_cap",
                    "upload_expired"
                  ],
                  "description": "Why a job failed or is waiting in `ready`, for example `insufficient_credits` (the job stays `ready`) or `invalid_csv`. Every value: https://email-validation.org/docs/api/bulk/#errors.",
                  "x-nullable": true,
                  "x-ms-summary": "Error Code"
                },
                "webhook_endpoint_id": {
                  "type": "string",
                  "description": "Registered webhook endpoint notified about this job.",
                  "x-nullable": true,
                  "x-ms-summary": "Webhook Endpoint ID"
                },
                "created_at": {
                  "type": "string",
                  "format": "date-time",
                  "description": "When the job was created.",
                  "x-ms-summary": "Created At"
                },
                "started_at": {
                  "type": "string",
                  "format": "date-time",
                  "x-nullable": true,
                  "x-ms-summary": "Started At"
                },
                "finished_at": {
                  "type": "string",
                  "format": "date-time",
                  "x-nullable": true,
                  "x-ms-summary": "Finished At"
                },
                "expires_at": {
                  "type": "string",
                  "format": "date-time",
                  "description": "When the uploaded file and the results are deleted (30 days after upload; results of a list that finishes in its last day are kept for 7 days after it finishes).",
                  "x-ms-summary": "Expires At"
                }
              },
              "required": [
                "id",
                "status",
                "filename",
                "total_rows",
                "unique_emails",
                "duplicates",
                "syntax_invalid",
                "local_answered",
                "processed",
                "credits_reserved",
                "credits_charged",
                "counts",
                "error_code",
                "webhook_endpoint_id",
                "created_at",
                "started_at",
                "finished_at",
                "expires_at"
              ],
              "description": "A bulk job. Counters are `null` until the file has been read (`analyzing`)."
            },
            "examples": {
              "application/json": {
                "id": "job_3Fv8QpL2xM7nC1rT9kW4yB",
                "status": "queued",
                "filename": "newsletter-2026-11.csv",
                "total_rows": 12480,
                "unique_emails": 12102,
                "duplicates": 378,
                "syntax_invalid": 41,
                "local_answered": 41,
                "processed": 0,
                "credits_reserved": 12061,
                "credits_charged": 0,
                "counts": {},
                "error_code": null,
                "webhook_endpoint_id": "whk_9Lp4XcV2nB7mQ1tR6zK3wF",
                "created_at": "2026-10-20T09:30:00.000Z",
                "started_at": "2026-10-20T09:30:41.000Z",
                "finished_at": null,
                "expires_at": "2026-11-19T09:30:00.000Z"
              }
            }
          }
        }
      }
    },
    "/v1/bulk/{id}/results": {
      "get": {
        "operationId": "getBulkJobResults",
        "summary": "Download bulk results (CSV)",
        "description": "Streams the results of a `completed` job as CSV (UTF-8). Our columns are appended to yours in this order: `ev_status`, `ev_reason`, `ev_action`, `ev_free_email`, `ev_role_account`, `ev_disposable`, `ev_catch_all_domain`, `ev_did_you_mean`, `ev_mx_found`, `ev_mx_record`, `ev_smtp_provider`, `ev_domain_age_days`. Rows that repeat an address get the same result.",
        "tags": ["Bulk jobs"],
        "x-ms-visibility": "important",
        "produces": ["text/plain"],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "type": "string",
            "pattern": "^job_[0-9A-Za-z]{22}$",
            "description": "Bulk job id.",
            "x-ms-summary": "Job ID",
            "x-ms-visibility": "important",
            "x-ms-url-encoding": "single"
          },
          {
            "name": "filter",
            "in": "query",
            "required": false,
            "type": "string",
            "default": "all",
            "maxLength": 64,
            "pattern": "^(all|(valid|invalid|catch_all|unknown|disposable)(,(valid|invalid|catch_all|unknown|disposable))*)$",
            "description": "`all`, one status, or a comma-separated list of statuses (for example `valid,catch_all`). The old name `risky` is still accepted and stands for `catch_all,disposable`, and so are `deliverable` (`valid`) and `undeliverable` (`invalid`); any other value is refused.",
            "x-ms-summary": "Statuses",
            "x-ms-visibility": "important"
          },
          {
            "name": "columns",
            "in": "query",
            "required": false,
            "type": "string",
            "enum": ["original", "email_only"],
            "default": "original",
            "description": "`original` keeps every column of your file; `email_only` returns the address and our columns.",
            "x-ms-summary": "Columns",
            "x-ms-visibility": "advanced"
          },
          {
            "name": "escape_formulas",
            "in": "query",
            "required": false,
            "type": "boolean",
            "default": true,
            "description": "Prefix cells from your file that start with `=`, `+`, `-` or `@` (also after a comma, semicolon, tab or line break inside a cell, for spreadsheets set to another list separator) so spreadsheets do not run them as formulas. Our own columns and the address column are always escaped.",
            "x-ms-summary": "Escape Formulas",
            "x-ms-visibility": "advanced"
          }
        ],
        "responses": {
          "200": {
            "description": "The CSV file.",
            "schema": {
              "type": "string",
              "x-ms-summary": "File Content",
              "description": "The CSV file."
            },
            "examples": {
              "text/plain": "email,first_name,ev_status,ev_reason,ev_action,ev_free_email,ev_role_account,ev_disposable,ev_catch_all_domain,ev_did_you_mean,ev_mx_found,ev_mx_record,ev_smtp_provider,ev_domain_age_days\naccepted@sandbox.email-validation.org,Ana,valid,accepted,send,false,false,false,false,,true,mx.sandbox.email-validation.org,other,\ncatch_all@sandbox.email-validation.org,Ben,catch_all,catch_all,send_with_caution,false,false,false,true,,true,mx.sandbox.email-validation.org,other,\n"
            }
          }
        }
      }
    },
    "/v1/status": {
      "get": {
        "operationId": "getServiceStatus",
        "summary": "Get service status",
        "description": "Public status of each component. No key needed. Updated every minute; answers may be up to 30 seconds old. When no status information is available the answer is `503` with `Retry-After: 60`.",
        "tags": ["Service"],
        "x-ms-visibility": "advanced",
        "responses": {
          "200": {
            "description": "Current status.",
            "schema": {
              "type": "object",
              "properties": {
                "status": {
                  "type": "string",
                  "enum": ["operational", "degraded", "outage"],
                  "x-ms-summary": "Status"
                },
                "components": {
                  "type": "object",
                  "properties": {
                    "website": {
                      "type": "string",
                      "enum": ["operational", "degraded", "outage"],
                      "x-ms-summary": "Website"
                    },
                    "api": {
                      "type": "string",
                      "enum": ["operational", "degraded", "outage"],
                      "x-ms-summary": "API"
                    },
                    "bulk": {
                      "type": "string",
                      "enum": ["operational", "degraded", "outage"],
                      "x-ms-summary": "Bulk"
                    },
                    "sign_in": {
                      "type": "string",
                      "enum": ["operational", "degraded", "outage"],
                      "x-ms-summary": "Sign In"
                    },
                    "payments": {
                      "type": "string",
                      "enum": ["operational", "degraded", "outage"],
                      "x-ms-summary": "Payments"
                    },
                    "support": {
                      "type": "string",
                      "enum": ["operational", "degraded", "outage"],
                      "x-ms-summary": "Support"
                    }
                  },
                  "required": ["website", "api", "bulk", "sign_in", "payments", "support"],
                  "x-ms-summary": "Components"
                },
                "updated_at": {
                  "type": "string",
                  "format": "date-time",
                  "description": "When this status was computed.",
                  "x-ms-summary": "Updated At"
                }
              },
              "required": ["status", "components", "updated_at"]
            },
            "examples": {
              "application/json": {
                "status": "operational",
                "components": {
                  "website": "operational",
                  "api": "operational",
                  "bulk": "operational",
                  "sign_in": "operational",
                  "payments": "operational",
                  "support": "operational"
                },
                "updated_at": "2026-10-20T09:30:00.000Z"
              }
            }
          }
        }
      }
    }
  },
  "securityDefinitions": {
    "api_key": {
      "type": "apiKey",
      "in": "header",
      "name": "Authorization"
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "tags": [
    {
      "name": "Validation"
    },
    {
      "name": "Account"
    },
    {
      "name": "Bulk jobs"
    },
    {
      "name": "Service"
    }
  ],
  "x-ms-capabilities": {
    "testConnection": {
      "operationId": "getCredits"
    }
  },
  "x-ms-connector-metadata": [
    {
      "propertyName": "Website",
      "propertyValue": "https://email-validation.org"
    },
    {
      "propertyName": "Privacy policy",
      "propertyValue": "https://email-validation.org/legal/privacy/"
    },
    {
      "propertyName": "Categories",
      "propertyValue": "Marketing;Data"
    }
  ]
}
