Classify Endpoint
The classify endpoint analyzes an email address or domain and returns provider information and classification details.
Request
GET /v1/classify
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| email | string | Yes* | The email address to classify |
| domain | string | Yes* | The domain to classify |
| enrich | string | No | Set to true to include company information for the domain |
*At least one of email or domain must be provided. If both are provided, the domain from the email takes precedence.
Examples
cURL
# Classify by email
curl -H "Authorization: Bearer sk_live_YOUR_KEY" \
"https://emailkind.com/v1/[email protected]"
# Classify by domain
curl -H "Authorization: Bearer sk_live_YOUR_KEY" \
"https://emailkind.com/v1/classify?domain=google.com"
# Classify with company enrichment
curl -H "Authorization: Bearer sk_live_YOUR_KEY" \
"https://emailkind.com/v1/classify?domain=stripe.com&enrich=true"
Python SDK
from emailkind import EmailKind
client = EmailKind("sk_live_YOUR_KEY")
result = client.classify(email="[email protected]")
if result.classification.is_disposable:
print("Blocked: disposable email")
elif result.classification.is_business:
print(f"Business email from {result.provider.name}")
Node.js SDK
import EmailKind from 'emailkind';
const client = new EmailKind('sk_live_YOUR_KEY');
const result = await client.classify({ email: '[email protected]' });
if (result.classification.is_disposable) {
console.log('Blocked: disposable email');
} else if (result.classification.is_business) {
console.log('Business email from', result.provider.name);
}
Go SDK
client := emailkind.NewClient("sk_live_YOUR_KEY")
result, _ := client.Classify(ctx, &emailkind.ClassifyParams{
Email: "[email protected]",
})
if result.Classification.IsDisposable {
fmt.Println("Blocked: disposable email")
} else if result.Classification.IsBusiness {
fmt.Println("Business email from", result.Provider.Name)
}
PHP
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => "https://emailkind.com/v1/classify?" . http_build_query(["email" => "[email protected]"]),
CURLOPT_HTTPHEADER => ["Authorization: Bearer sk_live_YOUR_KEY"],
CURLOPT_RETURNTRANSFER => true,
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
if ($result["classification"]["is_disposable"]) {
echo "Blocked: disposable email";
}
Ruby
require "net/http"
require "json"
uri = URI("https://emailkind.com/v1/[email protected]")
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer sk_live_YOUR_KEY"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body)
if data["classification"]["is_disposable"]
puts "Blocked: disposable email"
elsif data["classification"]["is_business"]
puts "Business email from #{data["provider"]["name"]}"
end
Response
{
"success": true,
"request_id": "req_abc123",
"email": "[email protected]",
"domain": "gmail.com",
"provider": {
"id": "gmail",
"name": "Gmail",
"type": "personal"
},
"classification": {
"is_business": false,
"is_free": true,
"is_disposable": false,
"is_education": false,
"is_custom_domain": false,
"is_role": false
},
"mx": [
"gmail-smtp-in.l.google.com",
"alt1.gmail-smtp-in.l.google.com"
],
"confidence": 0.98,
"cached": true
}
Response with enrichment (enrich=true)
{
"success": true,
"request_id": "req_def456",
"domain": "stripe.com",
"provider": {
"id": "google_workspace",
"name": "Google Workspace",
"type": "business"
},
"classification": {
"is_business": true,
"is_free": false,
"is_disposable": false,
"is_education": false,
"is_custom_domain": true,
"is_role": false
},
"company": {
"name": "Stripe, Inc",
"source": "ssl",
"has_favicon": true
},
"mx": ["aspmx.l.google.com"],
"confidence": 0.98,
"cached": true
}
Response fields
| Field | Type | Description |
|---|---|---|
| success | boolean | Whether the request succeeded |
| request_id | string | Unique request identifier for support |
| email | string | The submitted email (empty if domain-only request) |
| normalized_email | string | Canonical mailbox address — only present when an email was submitted and provider-specific alias rules changed it (see Alias normalization) |
| domain | string | The domain that was analyzed |
| provider.id | string | Unique provider identifier (e.g. google_workspace, gmail, microsoft_365) |
| provider.name | string | Human-readable provider name |
| provider.type | string | One of: business, personal, disposable, hosting, education, isp, self_hosted, unknown |
| classification.is_business | boolean | True if the email is a business/work email |
| classification.is_free | boolean | True if using a free email provider |
| classification.is_disposable | boolean | True if using a disposable/temporary email service |
| classification.is_education | boolean | True if the domain belongs to an educational institution |
| classification.is_custom_domain | boolean | True if using a custom domain with a known provider |
| classification.is_role | boolean | True if the local-part is a role/functional account (info@, support@, sales@, ...). Always false for domain-only requests |
| mx | string[] | MX records found for the domain |
| confidence | number | Confidence score from 0.0 to 1.0 |
| cached | boolean | Whether the DNS result came from cache |
| company | object | Company information (only present when enrich=true) |
| company.name | string | Company name resolved from the domain |
| company.source | string | Resolution source: ssl, website, rdap, or domain |
| company.has_favicon | boolean | Whether the domain serves a favicon (active website signal) |
Company enrichment sources
| Source | Description | Reliability |
|---|---|---|
| ssl | Organization field from the TLS certificate (EV/OV certs) | High — official legal entity name |
| website | Extracted from OpenGraph meta tags (og:site_name, og:title) or <title> | Medium — may include taglines |
| rdap | WHOIS/RDAP registrant organization | Medium — often redacted (GDPR) |
| domain | Derived from the domain name itself (fallback for bot-protected sites) | Low — best-effort capitalization |
Provider types
| Type | Description | Examples |
|---|---|---|
| business | Business email provider | Google Workspace, Microsoft 365, Zoho |
| personal | Free personal email | Gmail, Outlook.com, Yahoo Mail |
| disposable | Temporary/throwaway email | Guerrilla Mail, Mailinator |
| hosting | Hosting provider email | GoDaddy, OVH, Namecheap |
| education | Educational institution | University email systems |
| isp | Internet service provider email | Comcast, AT&T, Vodafone |
| self_hosted | Self-hosted mail server | Custom MX records pointing to own domain |
| unknown | Cannot be determined | No MX records or unrecognized provider |
Classification examples
| Email | Provider | is_business | is_free | is_disposable | is_education |
|---|---|---|---|---|---|
| [email protected] | Google Workspace | true | false | false | false |
| [email protected] | Gmail | false | true | false | false |
| [email protected] | Disposable | false | false | true | false |
| [email protected] | Microsoft 365 | true | false | false | true |
| [email protected] | Yahoo Mail | false | true | false | false |
| [email protected] | Cloudflare Email Routing | true | false | false | false |
Role accounts
When you submit a full email, classification.is_role flags addresses whose
local-part is a function or team rather than an individual — info@, support@,
sales@, admin@, billing@, and similar. The check is based on the local-part
only (RFC 2142 names plus common B2B conventions), so it is always false for
domain-only requests.
A +tag subaddress is ignored before matching, so [email protected]
is still detected as a role account.
curl -H "Authorization: Bearer sk_live_YOUR_KEY" \
"https://emailkind.com/v1/[email protected]"
# => "classification": { ..., "is_role": true }
Role accounts are technically valid but often warrant different handling — for example, routing them to a shared inbox, or gating them out of self-serve trials.
Alias normalization
Many providers treat several literal addresses as the same mailbox. When the
provider's aliasing rules are known, the response includes a normalized_email
field with the canonical form. This is useful for deduplicating users and
preventing duplicate signups.
| Submitted | normalized_email | Rule |
|---|---|---|
| [email protected] | [email protected] | Gmail ignores dots and +tags |
| [email protected] | [email protected] | Gmail dot rule (googlemail.com) |
| [email protected] | [email protected] | +tag subaddressing |
| [email protected] | [email protected] | +tag subaddressing |
normalized_email is omitted when:
- only a
domainwas submitted (no local-part), or - the submitted address is already canonical, or
- the domain is a custom/self-hosted domain or an unrecognized provider.
We deliberately never normalize custom domains: their local-part rules are unknown to us, and collapsing two distinct mailboxes would be a destructive error. Normalization is limited to an allow-list of providers whose alias rules are documented and stable (Gmail/Google, Outlook/Hotmail/Live, iCloud, Yahoo, Proton, Fastmail).
Internationalized domains (IDN)
Unicode domains are accepted and normalized to their ASCII (punycode) form
before lookup, so café.fr and xn--caf-dma.fr are treated identically. The
domain field in the response is always returned in its canonical ASCII form.
Headers
The response includes the following headers:
| Header | Description |
|---|---|
| X-Request-ID | Unique request identifier |
| X-Cache | HIT if the DNS result was cached, MISS otherwise |
| X-Response-Time | Time taken to process the request |
| X-RateLimit-Limit | Your plan's rate limit per minute |
| X-RateLimit-Remaining | Remaining requests in the current window |
| X-RateLimit-Reset | Unix timestamp when the rate limit resets |