# SOP: Enrich Contacts with Hunter.io

**Purpose:** Use Hunter.io API to find verified email addresses and contact details for companies, bypassing website bot protections.

**When to Use:** 
- Website blocks automated scraping (CloudFlare, bot detection)
- Need verified email addresses for target companies
- Want executive/decision-maker contacts
- Have company domain but no contact details

**Cost:** Free tier = 50 searches/month (current plan)

---

## Prerequisites

✅ Hunter.io API key: `fda8536970076bc3228c5b5fa6e19fdc407c43c9`  
✅ Company domain names (e.g., seeka.co.nz)  
✅ Google Sheet access for upload

---

## Process

### Step 1: Prepare Target List

Create a list of companies with their domains:

```python
domains = [
    ("Company Name", "domain.com"),
    ("Another Company", "company.co.nz"),
]
```

### Step 2: Run Hunter.io Domain Search

```python
import requests
import json
import csv
import time

API_KEY = "fda8536970076bc3228c5b5fa6e19fdc407c43c9"

results = []

for company, domain in domains:
    url = f"https://api.hunter.io/v2/domain-search?domain={domain}&api_key={API_KEY}&limit=5"
    
    response = requests.get(url)
    data = response.json()
    
    if 'data' in data and 'emails' in data['data']:
        emails = data['data']['emails'][:3]  # Top 3 most relevant
        
        for email in emails:
            results.append({
                'Company': company,
                'Domain': domain,
                'Name': f"{email.get('first_name', '')} {email.get('last_name', '')}".strip(),
                'Title': email.get('position', 'Unknown'),
                'Email': email.get('value', ''),
                'Confidence': email.get('confidence', 0),
                'Verified': email.get('verification', {}).get('status', 'unknown'),
                'Department': email.get('department', ''),
                'Seniority': email.get('seniority', '')
            })
    
    time.sleep(1)  # Rate limit (1 req/sec recommended)
```

### Step 3: Save Results

```python
with open('enriched-contacts.csv', 'w', newline='', encoding='utf-8') as f:
    fieldnames = ['Company', 'Domain', 'Name', 'Title', 'Email', 'Confidence', 'Verified', 'Department', 'Seniority']
    writer = csv.DictWriter(f, fieldnames=fieldnames)
    writer.writeheader()
    writer.writerows(results)
```

### Step 4: Map to Google Sheet Format

Master sheet columns:
```
Company Name, Website, Country, State/Region, Primary Fruit, CA Storage Confirmed, 
Size, Qualified, Produce, Employee Count, Revenue, Notes, Contact Name, Contact Title, 
Contact Email, Contact Phone, Source
```

Mapping logic:
```python
for contact in enriched:
    row = [
        contact['Company'],              # Company Name
        contact['Domain'],               # Website
        'COUNTRY',                       # Country (e.g., 'NZ', 'US')
        '',                              # State/Region
        'Multi-produce',                 # Primary Fruit (adjust as needed)
        'Unknown',                       # CA Storage Confirmed
        '',                              # Size
        'Yes',                           # Qualified (Hunter verified = qualified)
        '',                              # Produce
        '',                              # Employee Count
        '',                              # Revenue
        f"Hunter.io {confidence}% confidence, {verified}",  # Notes
        contact['Name'],                 # Contact Name
        contact['Title'],                # Contact Title
        contact['Email'],                # Contact Email
        '',                              # Contact Phone
        'Hunter.io'                      # Source
    ]
```

### Step 5: Upload to Google Sheet

```bash
gog sheets update \
  --account jonny@jonnyshannon.com \
  --values-json '[["Company","domain.com","NZ","","Apples",...]]' \
  SPREADSHEET_ID \
  'New Zealand!A100'  # Adjust row number
```

---

## Quality Checks

### Before Upload:
- ✅ Confidence score ≥ 80% (Hunter.io reliability)
- ✅ Verified status = "valid" (when available)
- ✅ Title is executive/senior/decision-maker level
- ✅ Department is relevant (sales, executive, operations, management)

### Filter Out:
- ❌ Generic emails (info@, contact@, office@)
- ❌ Low confidence (<60%)
- ❌ Non-decision makers (unless specifically needed)

---

## Cost Tracking

**Check remaining searches:**
```bash
curl -s "https://api.hunter.io/v2/account?api_key=YOUR_KEY" | \
  python3 -c "import sys, json; d=json.load(sys.stdin)['data']; \
  print(f\"Requests: {d['requests']['searches']['used']}/{d['requests']['searches']['available']}\")"
```

**Current Plan:** Free (50 searches/month)  
**Upgrade:** $49/month = 500 searches

---

## Results Format

### What Hunter.io Returns:
```json
{
  "value": "john.doe@company.com",
  "type": "personal",
  "confidence": 95,
  "first_name": "John",
  "last_name": "Doe",
  "position": "Chief Executive Officer",
  "seniority": "executive",
  "department": "executive",
  "linkedin": "https://linkedin.com/in/johndoe",
  "verification": {
    "status": "valid",
    "date": "2026-02-11"
  }
}
```

### Key Fields:
- **Confidence:** 0-100 (≥90 = very reliable, 80-89 = reliable, <80 = uncertain)
- **Verification Status:** valid, invalid, accept_all, unknown
- **Seniority:** executive, senior, junior
- **Department:** executive, sales, marketing, operations, it, finance, etc.

---

## Example: NZ Coolstores (Feb 2026)

**Input:** 10 NZ produce companies  
**Output:** 29 verified contacts  
**Cost:** $0 (free tier)  
**Time:** ~2 minutes  
**Success Rate:** 100% (all 10 companies had emails)

**Top Results:**
- Seeka Limited: CEO, Business Dev Director, CIO (3 contacts, 96-99% confidence)
- EastPack Ltd: CTO, Director IT (2 contacts, 90-91% confidence)
- First Fresh NZ: CEO, Sales Director, Procurement Director (3 contacts, 97-99% confidence)

---

## Troubleshooting

### "No emails found"
- Company may not have public email presence
- Domain might be wrong (check website)
- Try alternate domains (company.com vs company.co.nz)

### "Rate limit exceeded"
- Free plan: 50 searches/month
- Wait until next month or upgrade plan
- Check usage: `curl https://api.hunter.io/v2/account?api_key=KEY`

### "Invalid API key"
- Verify key is correct
- Check Hunter.io account status

---

## Best Practices

1. **Target high-value companies first** - Don't waste searches on low-priority targets
2. **Batch similar companies** - Process 10-20 at a time, review before continuing
3. **Verify domains** - Wrong domain = wasted search
4. **Prefer .com/.co.nz over subdirectories** - Better results from root domains
5. **Check confidence scores** - Prioritize 90%+ for outreach
6. **Update notes field** - Include confidence and verification status
7. **Track usage monthly** - Don't hit limit mid-project

---

## Automation Script

**Location:** `/Users/max/.openclaw/workspace/postharvest/scrapers/enrich-hunter.py`

**Usage:**
```bash
python3 enrich-hunter.py --input companies.csv --output enriched.csv
```

**Input CSV format:**
```
Company Name,Domain
Seeka Limited,seeka.co.nz
EastPack Ltd,eastpack.co.nz
```

**Output:** Enriched CSV ready for Google Sheet upload

---

## Files

- **Script:** `scrapers/enrich-hunter.py`
- **Example output:** `NZ-companies-enriched.csv`
- **Upload script:** `add-nz-enriched.py`

---

**Created:** 2026-02-11  
**Last Used:** 2026-02-11 (10 NZ companies, 29 contacts, $0 cost)  
**Success Rate:** 100%  
**Version:** 1.0
