/v1/verifyv1Verify Email / Domain
Check whether an email address or domain belongs to a known disposable email provider. Returns a JSON response indicating whether the domain is disposable, along with the extracted domain.
Method
GET
Base URL
api.temp.sh
Auth
x-api-key header
GET https://temptrap.vercel.app/api/v1/verify?email=user@mailinator.comAuthentication
All requests must include a valid API key in the x-api-key request header. Keys are scoped to your project and tracked per-request in your usage log.
Required Header
x-api-keystringrequiredYour API key from the dashboardHow to find your key
Request
The endpoint accepts a single email (or its alias url) query parameter. It supports three input forms: a full email address, a bare domain, or a full URL. The domain is always extracted and normalised to lowercase before the check is performed.
Accepted Input Formats
| Input Type | Example | Extracted Domain |
|---|---|---|
| Email address | user@mailinator.com | mailinator.com |
| Full URL | https://guerrillamail.com | guerrillamail.com |
| Bare domain | tempmail.com | tempmail.com |
Parameters
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
email | string | required* | An email address, domain, or URL to check |
url | string | alias | Alias for email. Accepts the same value. email takes precedence if both are present. |
* One of email or url must be provided. If neither is present, the API returns 400.
Response
All verified requests — disposable or not — return 200 OK with a JSON body. The result describes the input as submitted, the extracted domain, and the disposable verdict.
Success Response
| Field | Type | Description |
|---|---|---|
email | string | The exact value submitted in the request |
isDisposable | boolean | true if the AI+heuristics verdict classifies this as disposable |
isTemp | boolean | Legacy alias for isDisposable — kept for backwards compatibility |
domain | string | The extracted domain used for the check |
score | number | 0–100 risk score — higher means more likely disposable |
confidence | enum | 'low', 'medium', or 'high' — how many signals contributed to the verdict |
explanation | string | One-sentence AI reasoning in plain English |
signals.inDisposableList | boolean | Domain matched the disposable-email-domains blocklist |
signals.mxValid | boolean | Domain has at least one valid MX record |
signals.mxProviders | string[] | MX hostnames returned by DNS |
signals.mxCatchAll | boolean? | Whether the domain accepts any address (catch-all) |
signals.smtpMailboxExists | boolean? | RCPT TO accepted (null = SMTP blocked/timeout) |
signals.smtpCatchAll | boolean? | Random probe also accepted — confirms catch-all |
signals.smtpError | string? | SMTP connection error message, if any |
signals.domainAgeDays | number? | Days since domain registration via RDAP |
signals.domainRegistrar | string? | Domain registrar name from RDAP |
signals.isNewDomain | boolean | true if domain age < 90 days |
signals.randomLookingLocalPart | boolean | Heuristic: high-entropy or consonant-only local part |
signals.numericHeavyUsername | boolean | Heuristic: >50% digits in the local part |
signals.suspiciousSubdomain | boolean | Heuristic: uses a known temp-mail subdomain pattern |
signals.heuristicScore | number | 0–40 additive penalty from pattern analysis |
cached | boolean | Result was served from 24h domain-level cache |
{
"email": "user@mailinator.com",
"isDisposable": true,
"isTemp": true,
"domain": "mailinator.com",
"score": 91,
"confidence": "high",
"explanation": "Known disposable provider. SMTP verification confirmed catch-all policy.",
"signals": {
"inDisposableList": true,
"mxValid": true,
"mxProviders": ["mx.mailinator.com"],
"mxCatchAll": true,
"smtpMailboxExists": true,
"smtpCatchAll": true,
"smtpError": null,
"domainAgeDays": 4621,
"domainRegistrar": "NameCheap, Inc.",
"isNewDomain": false,
"randomLookingLocalPart": false,
"numericHeavyUsername": false,
"suspiciousSubdomain": false,
"heuristicScore": 0
},
"cached": false
}
// Example with random-looking local part on a new domain:
{
"email": "xk92jd@tempinbox.co",
"isDisposable": true,
"isTemp": true,
"domain": "tempinbox.co",
"score": 88,
"confidence": "high",
"explanation": "New domain (18 days old) with random-looking address and no known MX provider.",
"signals": {
"inDisposableList": false,
"mxValid": true,
"mxProviders": ["mail.tempinbox.co"],
"mxCatchAll": null,
"smtpMailboxExists": null,
"smtpCatchAll": null,
"smtpError": "timeout",
"domainAgeDays": 18,
"domainRegistrar": "Unknown",
"isNewDomain": true,
"randomLookingLocalPart": true,
"numericHeavyUsername": false,
"suspiciousSubdomain": false,
"heuristicScore": 20
},
"cached": false
}Errors
All error responses return JSON with a single error field containing a plain-English message.
{ "error": "Missing x-api-key header" }Error Reference
| Status | Message |
|---|---|
| 400 | Missing URL or email parameter |
| 400 | Invalid format |
| 401 | Missing x-api-key header |
| 401 | Invalid API Key |
| 402 | Usage limit reached |
| 500 | Internal server error |
Code Examples
curl -X GET "https://temptrap.vercel.app/api/v1/verify?email=user@mailinator.com" \
-H "x-api-key: YOUR_API_KEY"Signup Protection Pattern (Next.js)
// app/api/auth/register/route.ts
export async function POST(req: Request) {
const { email, password } = await req.json();
// Verify before creating the account
const check = await fetch(
`https://temptrap.vercel.app/api/v1/verify?email=${encodeURIComponent(email)}`,
{ headers: { "x-api-key": process.env.TEMP_API_KEY! } }
);
const { isDisposable } = await check.json();
if (isDisposable) {
return Response.json(
{ error: "Disposable email addresses are not allowed." },
{ status: 400 }
);
}
// Proceed with registration...
}Try It
Send a live request directly from this page. Your API key is sent directly to the API — it is never stored or logged by the docs page.