This guide covers the most common issues developers encounter when integrating with the Emailyze API, along with their causes and resolutions.
#### "I get 401 Unauthorized errors"
Cause: The API key is missing, malformed, or the authentication header is incorrect.
Fix:
1. Confirm you are passing the API key via the X-API-Key header:
X-API-Key: YOUR_API_KEY
Alternatively, use the query parameter: ?key=YOUR_API_KEY.
2. Verify the key is active. Log in to your dashboard, navigate to API Keys, and confirm the key is not revoked.
3. Check for trailing whitespace or line breaks in the key value — copy-paste errors are common.
4. All API URLs require a trailing slash. A request to /v1/check (without the trailing slash) will not match and may return a redirect or 404, not a 401. Use /v1/check/.
#### "My domain always returns unknown"
Cause: The domain is not yet in the Emailyze database. New or obscure domains may not have been processed by the ETL pipeline.
Fix:
1. New domains added to source lists take up to 1 hour to propagate through the full ETL pipeline (fetch → normalize → merge → score → publish).
2. When a domain is checked via the API and not found, Emailyze creates a Domain record and queues an asynchronous MX lookup. Subsequent checks within 24 hours will return the enriched result.
3. For known-disposable domains that consistently return unknown, use the Feedback endpoint (POST /v1/feedback/) to report a false negative. The team reviews feedback and updates classifications.
#### "Risk score is 0 for everything"
Cause: The domain database has not been seeded, or the scoring pipeline has not run.
Fix:
1. If you are running a self-hosted instance, ensure you have run python3 manage.py ingest_domains to populate the domain list. The scoring stage runs automatically after ingestion.
2. On the hosted API, a risk score of 0 for all results (including known disposable providers) indicates a pipeline issue. Contact support at hi@emailyze.dev with example domains and timestamps.
3. A risk score of 0 for a specific domain is valid if the domain is unclassified or newly created. Check the provider_type field — an unknown provider type with a score of 0 is expected for newly created domains.
#### "Batch returns fewer results than I sent"
Cause: The batch API automatically deduplicates email addresses within a single request.
Fix:
This is expected behavior. If you submit {"emails": ["a@example.com", "a@example.com", "b@example.com"]}, the API deduplicates and returns two results. The response array length equals the number of unique email addresses, not the total number submitted.
If you need to map results back to your original list (including duplicates), deduplicate your list before sending, or build a lookup map by email address from the response.
#### "I'm getting 429 Too Many Requests"
Cause: Your request rate or daily limit has been exceeded for your plan.
Plan limits:
| Plan | Rate Limit | Daily Limit | |------|-----------|------------| | Free | 1 req/s | 1,000 calls/day | | Starter | 10 req/s | 10,000 calls/day | | Growth | 50 req/s | 100,000 calls/day | | Enterprise | Custom | Custom |
Fix:
1. Implement exponential backoff when you receive a 429. Wait before retrying — start with 1 second, double on each retry, cap at 30 seconds.
2. For batch workloads, use POST /v1/check/batch/ with up to 1,000 emails per request instead of making individual single-check calls. Batch requests are far more efficient for throughput.
3. If you consistently hit daily limits, upgrade your plan via the dashboard or contact support for a custom limit.
4. Check your current daily usage in the dashboard under Insights to understand your consumption pattern before upgrading.
#### "Results differ between /v1/check/ and my local download"
Cause: The JSONL download (GET /v1/download/) is a point-in-time snapshot refreshed hourly. The live API reflects the current database state, which may have been updated since the last snapshot.
Fix:
1. The download endpoint publishes a new snapshot approximately every hour. If you are using the download for local lookups, refresh it hourly to stay current.
2. For real-time accuracy (especially for newly classified domains), use the live /v1/check/ endpoint rather than a stale local snapshot.
3. Classification changes (e.g., a domain reclassified from unknown to disposable) appear in the live API immediately but only in the download after the next hourly publish cycle.
#### "catch_all is null"
Cause: Catch-all probing is intentionally skipped for major providers (Gmail, Outlook, Yahoo, ProtonMail, and others) because these providers do not support meaningful SMTP probing.
Fix:
This is expected behavior, not an error. For domains hosted by major providers, catch_all will always be null. The is_disposable and risk_score fields are still populated based on the domain classification.
For custom or business domains, catch_all probing runs asynchronously and results are cached for 24 hours. If catch_all is null for a custom domain on first check, retry after 30–60 seconds; the result should populate.
#### Debug Checklist
Use this checklist when a request behaves unexpectedly:
X-API-Key present and correct? Is the key active in the dashboard?/? (e.g., /v1/check/ not /v1/check)Content-Type: application/json set?If you have worked through this checklist and the issue persists, contact support at hi@emailyze.dev with: