Cold Leads

Přechod s ověřováním e-mailů z Hunteru nebo Apolla na Cold Leads

Pro koho
Týmy, které dnes ověřují e-maily přes Hunter nebo Apollo
Problém
Kód pro ověřování je plný parametrů a hodnot stavu specifických pro dodavatele. Výměna endpointu bez jejich převodu potichu změní, na které adresy pipeline posílá.
Řešení
Každý parametr a každé pole odpovědi převeďte na protějšek v Cold Leads, to, co Cold Leads nenahrazuje (data o lidech, vyhledávání podle domény), ponechte, kde je, a použijte malý adaptér, aby stávající kód zachoval svou podobu.
Co získáte
Převodní tabulka pole po poli, adaptér v Pythonu, který z Cold Leads vrací pole ve stylu Hunteru, a tabulka nákladů na Cold Leads pro 1 000, 10 000 a 50 000 ověření měsíčně.

Adresy, identifikátory a výsledky v příkladech jsou ilustrativní. Doména example.com je vyhrazená pro dokumentaci, takže skutečná kontrola těchto adres vrátí invalid.

Ukázky kódu jsou ve všech jazycích stejné, komentáře v nich jsou anglicky.

Co se přesouvá a co zůstává

  • Přesouvá se: kontrola jednotlivých adres (Hunter Email Verifier) na POST /api/v1/verify, seznamy na POST /api/v1/verify/bulk (až 5 000 adres na úlohu) a odhady ze jména a domény (Hunter Email Finder) na POST /api/v1/find.
  • Zůstává: Domain Search od Hunteru i webové zdroje za jeho výsledky; od Apolla People Search, People Enrichment a Bulk People Enrichment. Cold Leads nemá databázi lidí ani firem; GET /api/v1/leads hledá jen v kontaktech ve vašem vlastním CRM Cold Leads.
  • Veřejné API Apolla nemá samostatný endpoint pro ověření; email_status přichází spolu s daty o osobě. Pokud si Apollo kvůli datům ponecháte, můžete adresy, které vrací, před odesláním zkontrolovat v Cold Leads.

Email Verifier na POST /api/v1/verify

HunterCold LeadsPoznámka
GET /v2/email-verifier?email=…POST /api/v1/verify s JSON tělem {email}Cold Leads přijímá POST s JSON tělem.
query parametr api_key, hlavička X-API-KEY nebo Authorization: Bearerhlavička x-api-key nebo Authorization: BearerKlíče v query stringu se nepřijímají.
Bez časového parametru; 202, dokud kontrola ještě běžítimeout_ms, 1 000 až 30 000Cold Leads odpoví, až je kontrola hotová nebo je časový limit vyčerpán (pak risky, důvod timeout).
data.status validstatus valid s posledním důvodem okvalid se smtp_unreachable znamená, že se schránka nekontrolovala.
data.status invalidstatus invalid, důvod mailbox_missing, no_mx nebo syntax
data.status accept_allstatus risky, důvod catch_all, catch_all true
data.status disposabledisposable true (status risky, nebo invalid, když doména nemá MX)Vestavěný seznam 40 jednorázových e-mailových domén.
data.status webmailBez obdobyWebmailové adresy se kontrolují jako všechny ostatní.
data.status unknownstatus risky, důvod smtp_unknown nebo timeout
data.scorescore (0 až 100)Jiná stupnice; rozhodujte podle reasons, ne podle čísla.
data.regexpreasons obsahuje syntax, když kontrola syntaxe selže
data.mx_recordsmx: první MX host, nebo null, když doména nemá MX ani A záznam (důvod no_mx)
data.smtp_serversmtp_unreachable, když se přes SMTP nepodařilo spojit s žádným poštovním serveremok, catch_all a mailbox_missing znamenají, že poštovní server na kontrolu příjemce odpověděl.
data.smtp_checkposlední důvod ok nebo catch_allPoštovní server adresu přijal.
data.accept_allcatch_allMá význam, jen když poštovní server odpověděl (poslední důvod ok, catch_all nebo mailbox_missing).
data.gibberish, data.block, data.sourcesBez obdoby

Email Finder na POST /api/v1/find

HunterCold LeadsPoznámka
domaindomainURL se zkrátí na host (z https://www.example.com/about se stane example.com).
companyBez obdobyDoména je povinná.
first_name, last_namefirst, lastDiakritika se odstraní a ostatní nelatinkové znaky se vypustí, takže jména nejdřív přepište do latinky.
full_namenameRozdělí se u první mezery na first a last.
linkedin_handle, max_durationBez obdoby
data.emailemailnull, když nešlo sestavit žádného kandidáta, například když doména nemá MX.
data.scoreconfidence (0 až 100)
data.verification.statusmethodverified jen tehdy, když poštovní server schránku potvrdil; pattern pro odhad z běžných vzorů adres; none, když se nic nenašlo.
data.accept_allcatch_all
data.position, twitter, linkedin_url, phone_number, company, sourcesBez obdoby
(žádné)candidatesAdresy sestavené z běžných vzorů, každá se stavem své kontroly, pokud se kontrolovala.

Adaptér pro přímou náhradu

Pokud se váš kód větví podle názvů polí Hunteru, tyto dvě funkce vracejí z Cold Leads stejnou strukturu a navíc surovou odpověď pod klíčem coldleads. Převod je záměrně konzervativní: adresa, jejíž schránka se nekontrolovala (smtp_unreachable), se stane unknown, ne valid.

hunter_adapter.py
# pip install httpx
# Drop-in helpers for code written against Hunter's email-verifier and email-finder.
# They call Cold Leads and return Hunter-style fields, plus the raw Cold Leads answer.
import os

import httpx

cold = httpx.Client(
    base_url="https://coldleads.app/api/v1",
    headers={"x-api-key": os.environ["COLDLEADS_API_KEY"]},  # the key goes in a header, never in the URL
    timeout=40.0,
)

# a mail server answered the SMTP probe only when the last reason is one of these
PROBED = {"ok", "catch_all", "mailbox_missing"}


def email_verifier(email: str) -> dict:
    r = cold.post("/verify", json={"email": email, "timeout_ms": 20000})
    r.raise_for_status()
    c = r.json()
    last = c["reasons"][-1]
    if c["disposable"] and last not in ("syntax", "no_mx"):
        status = "disposable"
    elif last == "ok":
        status = "valid"
    elif last == "catch_all":
        status = "accept_all"
    elif last in ("mailbox_missing", "no_mx", "syntax"):
        status = "invalid"
    else:
        # smtp_unreachable (mailbox not checked), smtp_unknown or timeout: not verified
        status = "unknown"
    return {
        "email": c["email"],
        "status": status,
        "score": c["score"],
        "regexp": last != "syntax",
        "disposable": c["disposable"],
        "mx_records": c["mx"] is not None,
        "smtp_check": last in ("ok", "catch_all"),
        "accept_all": c["catch_all"] if last in PROBED else None,  # None: not tested
        "coldleads": c,
    }


def email_finder(domain: str, first_name: str = "", last_name: str = "", full_name: str = "") -> dict:
    body = {"domain": domain, "first": first_name, "last": last_name}
    if full_name and not (first_name or last_name):
        body = {"domain": domain, "name": full_name}
    r = cold.post("/find", json=body)
    r.raise_for_status()
    c = r.json()
    return {
        "email": c["email"],
        "score": c["confidence"],
        "accept_all": c["catch_all"],
        # Cold Leads says "verified" only when a mail server confirmed the mailbox; a pattern guess is not verified
        "verification": {"status": "valid" if c["method"] == "verified" else None},
        "coldleads": c,
    }


if __name__ == "__main__":
    print(email_verifier("anna@example.com"))

Rozdíly v chování, se kterými počítejte

  • Kódy chyb: Cold Leads odpovídá 429 při překročení limitu požadavků (rate_limited, s Retry-After: 60) a při příliš mnoha otevřených hromadných úlohách (too_many_jobs) a 402 no_credits, když dojdou kredity. Hunter dokumentuje 403 pro svůj limit požadavků a 429 pro limit využití, takže ošetření chyb je nutné přepsat, ne jen přejmenovat.
  • Limit požadavků: 120 požadavků za minutu na klíč. U seznamů jedna hromadná úloha nahradí až 5 000 jednotlivých volání.
  • Každé volání stojí 1 kredit, i u výsledků z 30denní cache.
  • SMTP test schránky a accept-all proběhne jen tehdy, když Cold Leads dokáže otevřít SMTP spojení s poštovním serverem příjemce. Zda proběhl, říká pole reasons každého výsledku: smtp_unreachable znamená, že se schránka nekontrolovala.

Limity a náklady

Ověření za měsícKredityNáklady na Cold Leads za měsíc
1 0001 000$99: tarif Business, který zahrnuje 10 000 kreditů
10 00010 000$99
50 00050 000$299: $99 plus 40 dalších balíčků po 1 000 kreditech za $5

API je jen v tarifu Business, který lze platit i ročně ($999). Dohledání adresy čerpá stejné kredity, 1 kredit za volání. Měsíční kredity se počítají za kalendářní měsíc (UTC) a čerpají se před zakoupenými balíčky. Ceny jsou v amerických dolarech; může se připočíst daň.

Otázky

Má Cold Leads obdobu Domain Search od Hunteru nebo vyhledávání lidí v Apollu?

Ne. Cold Leads data o lidech neshromažďuje. GET /api/v1/leads hledá jen v kontaktech, které už máte ve svém CRM Cold Leads.

Budou moje stávající prahy skóre fungovat dál?

Spolehlivě ne, protože se stupnice liší. Rozhodujte místo toho podle pole status a posledního kódu důvodu: ok odeslat, catch_all a smtp_unknown zkontrolovat, mailbox_missing, no_mx a syntax vyřadit a smtp_unreachable označuje adresy, jejichž schránka se nekontrolovala.

Můžu v Cold Leads ověřit export z Apolla?

Ano. Pošlete adresy jako hromadné úlohy po nejvýš 5 000 a dotazujte se na výsledky, nebo použijte skript v Pythonu pro soubory CSV na tomto webu. Každá adresa stojí 1 kredit.

Jsou výsledky z cache levnější?

Ne. Výsledek z 30denní cache je označen cached: true a stojí 1 kredit jako každé jiné volání.