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
| Hunter | Cold Leads | Pozná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: Bearer | hlavička x-api-key nebo Authorization: Bearer | Klíče v query stringu se nepřijímají. |
| Bez časového parametru; 202, dokud kontrola ještě běží | timeout_ms, 1 000 až 30 000 | Cold Leads odpoví, až je kontrola hotová nebo je časový limit vyčerpán (pak risky, důvod timeout). |
| data.status valid | status valid s posledním důvodem ok | valid se smtp_unreachable znamená, že se schránka nekontrolovala. |
| data.status invalid | status invalid, důvod mailbox_missing, no_mx nebo syntax | |
| data.status accept_all | status risky, důvod catch_all, catch_all true | |
| data.status disposable | disposable true (status risky, nebo invalid, když doména nemá MX) | Vestavěný seznam 40 jednorázových e-mailových domén. |
| data.status webmail | Bez obdoby | Webmailové adresy se kontrolují jako všechny ostatní. |
| data.status unknown | status risky, důvod smtp_unknown nebo timeout | |
| data.score | score (0 až 100) | Jiná stupnice; rozhodujte podle reasons, ne podle čísla. |
| data.regexp | reasons obsahuje syntax, když kontrola syntaxe selže | |
| data.mx_records | mx: první MX host, nebo null, když doména nemá MX ani A záznam (důvod no_mx) | |
| data.smtp_server | smtp_unreachable, když se přes SMTP nepodařilo spojit s žádným poštovním serverem | ok, catch_all a mailbox_missing znamenají, že poštovní server na kontrolu příjemce odpověděl. |
| data.smtp_check | poslední důvod ok nebo catch_all | Poštovní server adresu přijal. |
| data.accept_all | catch_all | Má význam, jen když poštovní server odpověděl (poslední důvod ok, catch_all nebo mailbox_missing). |
| data.gibberish, data.block, data.sources | Bez obdoby |
Email Finder na POST /api/v1/find
| Hunter | Cold Leads | Poznámka |
|---|---|---|
| domain | domain | URL se zkrátí na host (z https://www.example.com/about se stane example.com). |
| company | Bez obdoby | Doména je povinná. |
| first_name, last_name | first, last | Diakritika se odstraní a ostatní nelatinkové znaky se vypustí, takže jména nejdřív přepište do latinky. |
| full_name | name | Rozdělí se u první mezery na first a last. |
| linkedin_handle, max_duration | Bez obdoby | |
| data.email | null, když nešlo sestavit žádného kandidáta, například když doména nemá MX. | |
| data.score | confidence (0 až 100) | |
| data.verification.status | method | verified 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_all | catch_all | |
| data.position, twitter, linkedin_url, phone_number, company, sources | Bez obdoby | |
| (žádné) | candidates | Adresy 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.
# 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íc | Kredity | Náklady na Cold Leads za měsíc |
|---|---|---|
| 1 000 | 1 000 | $99: tarif Business, který zahrnuje 10 000 kreditů |
| 10 000 | 10 000 | $99 |
| 50 000 | 50 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í.