{
  "openapi": "3.0.1",
  "info": {
    "title": "Email Verifier & Validator — Bulk Email List Cleaner, $0.75/1k",
    "description": "Clean a contact list end to end: syntax check, normalization, deduplication, disposable and role detection, MX lookup, 0-100 scoring and segmented CSV export (clean / risky / role / invalid). Reads addresses buried in free text. Flat $0.75 per 1,000 on every plan — duplicates are never charged.",
    "version": "0.2",
    "x-build-id": "RFX18bCHfj2v0Tg7L"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/yabanana99~email-list-cleaner-verifier/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-yabanana99-email-list-cleaner-verifier",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/acts/yabanana99~email-list-cleaner-verifier/runs": {
      "post": {
        "operationId": "runs-sync-yabanana99-email-list-cleaner-verifier",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor and returns information about the initiated run in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/runsResponseSchema"
                }
              }
            }
          }
        }
      }
    },
    "/acts/yabanana99~email-list-cleaner-verifier/run-sync": {
      "post": {
        "operationId": "run-sync-yabanana99-email-list-cleaner-verifier",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "inputSchema": {
        "type": "object",
        "properties": {
          "emails": {
            "title": "Email addresses (inline)",
            "type": "array",
            "description": "Addresses to check, one per item. Use this for quick runs; for real lists use <b>Contact files</b> below. Inline addresses and files are merged and deduplicated together.",
            "default": [
              "John.Doe+news@Gmail.com",
              "john.doe@gmail.com",
              "info@apify.com",
              "user@mailinator.com",
              "jane@gmial.com",
              "not-an-email"
            ],
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "title": "Contact files (CSV, XLSX, JSON)",
            "type": "array",
            "description": "Files to read. Each item is an object with exactly one of: <b>url</b> (http/https link to the file), <b>base64</b> (base64-encoded file content, data URIs accepted) or <b>key</b> (record key in a key-value store, with optional <b>store_id</b>). Add <b>filename</b> (e.g. <code>contacts.csv</code>) to help format detection. Supported: CSV, TSV, XLSX, JSON, JSON Lines and plain-text lists. Up to 20 files per run."
          },
          "email_column": {
            "title": "Email column",
            "type": "string",
            "description": "Name of the column (CSV/XLSX header or JSON field) holding the address. Leave empty to auto-detect: known header names first (email, e-mail, mail, correo, courriel…), then the column where most values contain '@'. The column actually used is reported in the run log."
          },
          "dedup": {
            "title": "Remove duplicates",
            "type": "boolean",
            "description": "<b>On</b>: one record per unique address (the deduplicated list you can re-import), with <code>occurrences</code> telling how many times it appeared. <b>Off</b>: one record per input row, duplicates flagged with <code>is_duplicate</code> and <code>duplicate_of</code>. Either way a duplicate is never charged twice.",
            "default": true
          },
          "normalize": {
            "title": "Normalize addresses",
            "type": "boolean",
            "description": "Lowercase the local part, apply provider rules (Gmail dots, googlemail.com → gmail.com, +tags) and convert IDN domains to punycode. Domains are always lowercased. Normalization is what makes <code>J.Smith+news@Gmail.com</code> and <code>jsmith@gmail.com</code> collapse into one contact.",
            "default": true
          },
          "plus_tag_handling": {
            "title": "Plus tags (+tag)",
            "enum": [
              "known_providers",
              "all",
              "keep"
            ],
            "type": "string",
            "description": "<b>Known providers</b> strips <code>+tag</code> only where the provider documents sub-addressing (Gmail, Outlook, iCloud, Proton, Fastmail, GMX…). <b>All domains</b> strips it everywhere (aggressive: '+' is a legal character on other domains). <b>Keep</b> never strips it.",
            "default": "known_providers"
          },
          "check_mx": {
            "title": "Check MX records (DNS)",
            "type": "boolean",
            "description": "Look up the domain's MX records. This is the evidence that a domain can receive mail at all; with it off, no address can reach the <b>clean</b> segment (see the README scoring table). One DNS lookup per unique domain, cached for the whole run.",
            "default": true
          },
          "check_smtp": {
            "title": "Probe mailboxes over SMTP (advanced, off by default)",
            "type": "boolean",
            "description": "Opens an SMTP conversation (RCPT TO) with the mail server. <b>Off by default on purpose:</b> port 25 is blocked on most datacenter networks and big providers accept every recipient, so results are frequently <code>inconclusive</code> — which is exactly what this Actor reports instead of guessing. Slow (sequential, one conversation at a time).",
            "default": false
          },
          "detect_disposable": {
            "title": "Detect disposable domains",
            "type": "boolean",
            "description": "Flag throw-away providers (mailinator, guerrillamail, temp-mail, mail.tm, 1secmail…) using a bundled offline list of 75,000+ domains, subdomains included.",
            "default": true
          },
          "detect_role": {
            "title": "Detect role accounts",
            "type": "boolean",
            "description": "Flag shared mailboxes such as <code>info@</code>, <code>support@</code>, <code>sales-eu@</code>, <code>noreply@</code>. This is <b>information, not a defect</b>: role addresses keep their score and are exported to <code>role.csv</code> as well, so you can keep them (B2B outreach) or subtract them (newsletters).",
            "default": true
          },
          "role_segment": {
            "title": "Role accounts belong to",
            "enum": [
              "clean",
              "risky"
            ],
            "type": "string",
            "description": "Where role mailboxes land. <b>clean</b> (default) keeps <code>ceo@</code>, <code>hello@</code>, <code>press@</code> in the clean segment — they are the target of most B2B outreach. Choose <b>risky</b> to move them out of <code>clean.csv</code>.",
            "default": "clean"
          },
          "score": {
            "title": "Score and segment",
            "type": "boolean",
            "description": "Compute the 0-100 score, the confidence level and the clean / risky / invalid segment. Turn it off to get raw fields only.",
            "default": true
          },
          "output_segments": {
            "title": "Export segment CSV files",
            "type": "boolean",
            "description": "Also write <code>clean.csv</code>, <code>risky.csv</code> and <code>invalid.csv</code> to the run's key-value store, ready to download and import. Requires <b>Score and segment</b>.",
            "default": true
          },
          "disposable_segment": {
            "title": "Disposable addresses go to",
            "enum": [
              "invalid",
              "risky"
            ],
            "type": "string",
            "description": "Disposable addresses are usually deliverable but worthless. By default they land in <b>invalid</b>; choose <b>risky</b> if you prefer to review them yourself.",
            "default": "invalid"
          },
          "extra_disposable_domains": {
            "title": "Extra disposable domains",
            "type": "array",
            "description": "Your own additions to the disposable list (domain only, e.g. <code>badmail.example</code>). Subdomains match too. Up to 5000 entries.",
            "items": {
              "type": "string"
            }
          },
          "disposable_list_url": {
            "title": "Disposable list URL (optional)",
            "type": "string",
            "description": "http(s) URL of your own disposable-domain list — one domain per line or a JSON array of strings. It is merged with the bundled list, so you can plug in a feed that updates faster than this Actor's releases."
          },
          "include_source_row": {
            "title": "Keep the original row",
            "type": "boolean",
            "description": "Copy the source row (all its columns) into <code>source_row</code>, so the cleaned output keeps names, companies and every other field. Up to 30 columns, 500 characters per value and 1000 characters per row.",
            "default": false
          },
          "max_emails": {
            "title": "Max emails per run",
            "minimum": 1,
            "maximum": 100000,
            "type": "integer",
            "description": "Safety cap on how many rows are processed (and therefore charged) in one run. Hard limit: 100000.",
            "default": 100000
          },
          "dns_concurrency": {
            "title": "DNS concurrency",
            "minimum": 1,
            "maximum": 32,
            "type": "integer",
            "description": "How many MX lookups run in parallel. DNS is I/O-bound so parallelism genuinely helps here; lookups are cached per domain, so a 50k list of Gmail addresses is still one lookup. Range 1-32.",
            "default": 5
          },
          "dns_timeout_seconds": {
            "title": "DNS timeout (seconds)",
            "minimum": 1,
            "maximum": 30,
            "type": "integer",
            "description": "Per-lookup timeout. A domain that times out is reported as <code>mx_status: timeout</code> with low confidence — never as valid or invalid. Range 1-30.",
            "default": 5
          },
          "max_file_size_mb": {
            "title": "Max file size (MB)",
            "minimum": 1,
            "maximum": 100,
            "type": "integer",
            "description": "Files larger than this are skipped with a warning instead of failing the run.",
            "default": 50
          },
          "smtp_from_email": {
            "title": "SMTP MAIL FROM address",
            "type": "string",
            "description": "Only used when SMTP probing is on. Use an address on a domain you control; a mismatched or unknown sender is a common reason for inconclusive results."
          },
          "smtp_helo_host": {
            "title": "SMTP HELO hostname",
            "type": "string",
            "description": "Only used when SMTP probing is on. Should be a hostname you control whose PTR matches the outgoing IP — which datacenter IPs usually cannot offer. Defaults to the container hostname."
          },
          "smtp_timeout_seconds": {
            "title": "SMTP timeout (seconds)",
            "minimum": 2,
            "maximum": 60,
            "type": "integer",
            "description": "Per-step timeout of the SMTP conversation. Range 2-60.",
            "default": 10
          },
          "max_smtp_checks": {
            "title": "Max SMTP probes",
            "minimum": 1,
            "maximum": 20000,
            "type": "integer",
            "description": "Budget of SMTP conversations per run; beyond it, addresses are reported as <code>inconclusive</code> with the reason. Protects the run from spending hours on unresponsive servers.",
            "default": 1000
          }
        }
      },
      "runsResponseSchema": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "actId": {
                "type": "string"
              },
              "userId": {
                "type": "string"
              },
              "startedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "finishedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "status": {
                "type": "string",
                "example": "READY"
              },
              "meta": {
                "type": "object",
                "properties": {
                  "origin": {
                    "type": "string",
                    "example": "API"
                  },
                  "userAgent": {
                    "type": "string"
                  }
                }
              },
              "stats": {
                "type": "object",
                "properties": {
                  "inputBodyLen": {
                    "type": "integer",
                    "example": 2000
                  },
                  "rebootCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "restartCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "resurrectCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "computeUnits": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "options": {
                "type": "object",
                "properties": {
                  "build": {
                    "type": "string",
                    "example": "latest"
                  },
                  "timeoutSecs": {
                    "type": "integer",
                    "example": 300
                  },
                  "memoryMbytes": {
                    "type": "integer",
                    "example": 1024
                  },
                  "diskMbytes": {
                    "type": "integer",
                    "example": 2048
                  }
                }
              },
              "buildId": {
                "type": "string"
              },
              "defaultKeyValueStoreId": {
                "type": "string"
              },
              "defaultDatasetId": {
                "type": "string"
              },
              "defaultRequestQueueId": {
                "type": "string"
              },
              "buildNumber": {
                "type": "string",
                "example": "1.0.0"
              },
              "containerUrl": {
                "type": "string"
              },
              "usage": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "integer",
                    "example": 1
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "usageTotalUsd": {
                "type": "number",
                "example": 0.00005
              },
              "usageUsd": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "number",
                    "example": 0.00005
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}