Getting Started
Quickstart
This guide takes you from no account to a working check. You will make two requests, compare what comes back, and use the result in a signup flow.
1. Get an API key
Create a free account. The free plan includes 1,000 credits per month and does not require a credit card.
Once you are signed in, open API Keys and copy your key.
2. Make your first request
Ask the API about an ordinary address. Replace YOUR_API_KEY with the key you just copied:
curl -X GET "https://api.usercheck.com/email/[email protected]" \
-H "Authorization: Bearer YOUR_API_KEY"
The response:
{
"status": 200,
"email": "[email protected]",
"normalized_email": "[email protected]",
"domain": "github.com",
"domain_age_in_days": 6871,
"mx": true,
"mx_records": [
{ "hostname": "github-com.mail.protection.outlook.com", "priority": 0 }
],
"mx_providers": [
{ "slug": "microsoft", "type": "mailbox", "grade": "professional" }
],
"spf": "relaxed",
"dmarc": "quarantine",
"disposable": false,
"public_domain": false,
"relay_domain": false,
"free_subdomain": false,
"alias": false,
"role_account": false,
"spam": false,
"did_you_mean": null
}
Every field is documented in the email endpoint reference. For now the one to look at is disposable, which is false: this address is not from a temporary email service.
Pro plans also return domain_authority, tld_trust, blocklisted, and disposable_provider.
3. Check a disposable address
Now ask about an address from a well-known temporary email service:
curl -X GET "https://api.usercheck.com/email/[email protected]" \
-H "Authorization: Bearer YOUR_API_KEY"
{
"status": 200,
"email": "[email protected]",
"normalized_email": "[email protected]",
"domain": "mailinator.com",
"domain_age_in_days": 8431,
"mx": true,
"mx_records": [
{ "hostname": "mail.mailinator.com", "priority": 1 },
{ "hostname": "mail2.mailinator.com", "priority": 1 }
],
"mx_providers": [],
"spf": "strict",
"dmarc": "reject",
"disposable": true,
"public_domain": false,
"relay_domain": false,
"free_subdomain": false,
"alias": false,
"role_account": false,
"spam": true,
"did_you_mean": null
}
disposable is now true, and so is spam.
Notice what did not change. mx is still true, spf is strict, dmarc is reject, and the domain is over 20 years old. Mailinator runs its email infrastructure carefully, so the fields that describe how well a domain is configured say nothing about whether its addresses are temporary. That is the question disposable answers, and it is why checking MX records alone does not catch disposable signups.
4. Use the result in your signup flow
const response = await fetch(
`https://api.usercheck.com/email/${encodeURIComponent(email)}`,
{ headers: { Authorization: `Bearer ${process.env.USERCHECK_API_KEY}` } },
);
const result = await response.json();
if (result.disposable) {
return { error: 'Please sign up with a permanent email address.' };
}
// Store both. Mail goes to the address as submitted; the normalized form is
// the one to enforce uniqueness on, so aliases of the same mailbox, such as
// [email protected], cannot open two accounts.
await createAccount({
email: result.email,
normalizedEmail: result.normalized_email,
});
This example acts on disposable alone. Which signals you act on, and whether you reject a signup or flag it for review, is your decision. The response fields reference describes what each one means.
Next steps
- Email endpoint and Domain endpoint for every field the API returns
- Concepts for what individual signals mean and how to read them
- Credits for what each request costs
- Gates to define rules in the dashboard instead of writing this logic in your application