Detect disposable email in two lines
A REST (Representational State Transfer) API for your backend and a drop-in snippet for your forms. This reference is generated from the live OpenAPI schema, so it always matches the running API.
Quickstart
The base URL is https://api.isitdisposable.com. Create an account and generate a secret key from the dashboard, then check an address from your backend in your language of choice:
Send either an email or a domain (at least one is required). An email has its domain extracted; a bare domain is checked directly.
curl https://api.isitdisposable.com/v1/check \
-H "Authorization: Bearer sk_live_…" \
-H "content-type: application/json" \
-d '{"email": "[email protected]"}'A disposable address comes back like this:
{
"checked": true,
"normalized_email": "[email protected]",
"domain": "mailinator.com",
"disposable": true,
"mx_valid": true,
"role_account": false,
"relay": false,
"public_domain": false,
"spam_risk": false,
"did_you_mean": null,
"mx_records": ["mail.mailinator.com", "mail2.mailinator.com"],
"action": "block",
"reason": "disposable"
}action is one of allow, warn, or block; treat checked: false as allow.
The API fails open. Over quota or for an inactive subscription it still returns HTTP 200 with checked: false and action: "allow", so your form never breaks. Treat allow as do nothing.
Authentication
Send your key as a bearer token: Authorization: Bearer <key>. There are two kinds:
- sk_… secret keys are for server side use only. Keep them out of the browser and any public repository.
- pk_… publishable keys are safe in the browser. Each is restricted to the origins you list, so a lifted key only works from your approved sites. The snippet uses a publishable key.
API reference
Check one email or domain
Run detection on a single email address or bare domain. Send `email` or `domain`; at least one is required. An email has its domain extracted and checked; a bare domain is checked directly. When the account is over quota or not in a serving state the response fails open: HTTP 200 with `checked` false and `action` "allow", so a customer's form keeps working. The snippet treats `action` "allow" as do nothing.
Request body
| Field | Type | Description |
|---|---|---|
| string | Email address to check. | |
| domain | string | Bare domain to check. |
Response
| Field | Type | Description |
|---|---|---|
| checkedreq | boolean | Whether the address was actually evaluated. False on a safe fail-open response (for example over quota or an inactive subscription); when false, treat the result as allow and ignore the signals. |
| normalized_email | string | The submitted email, trimmed and lowercased. Null when only a domain was sent. |
| domain | string | The domain that was checked. |
| disposable | boolean | The core verdict: true when the domain belongs to a disposable or throwaway email provider. Null when the address was not checked. |
| mx_valid | boolean | Whether the domain has valid mail-exchange (MX) records and can receive mail. DNS-level only; no mailbox is ever probed. |
| role_account | boolean | Whether the local part is a role address (for example info@, support@, admin@) rather than a person. |
| relay | boolean | Whether the domain is a forwarding or relay or alias-masking provider. |
| public_domain | boolean | Whether the domain is a public consumer mailbox provider (for example gmail.com). |
| spam_risk | boolean | Whether the domain appears on a spam or abuse reputation list. Opt-in, off by default, and never affects the core disposable verdict. |
| did_you_mean | string | A suggested correction when the domain looks like a typo of a common provider (for example gmial.com for gmail.com), or null. |
| mx_records | string[] | The resolved MX hostnames, or an empty list when there are none. Null on a fail-open response (when checked is false). |
| actionreq | string | The recommended action for this result under the account's enforcement policy: one of allow, warn, or block. The platform never blocks on your behalf; your snippet or caller applies it. |
| reason | string | A short code explaining the action or verdict. Examples: disposable, mx_invalid, relay, role_account, public_domain, spam_risk (the signal that fired), dns_unavailable, quota_exceeded, subscription_inactive, account_blocklist, account_allowlist. Treat unknown codes gracefully, since the set can grow. Null when no specific reason applies. |
Errors
- 400: Invalid request: missing input, or a batch over the cap.
- 401: Missing or revoked API key.
- 403: Publishable key used from an Origin not on its allowlist.
- 429: Rate limit exceeded; retry after the Retry-After header.
Check up to 100 emails or domains
Check up to 100 addresses synchronously. Items are independent: an invalid item is reported and never billed without failing the batch. A request over the cap returns HTTP 400.
Request body
| Field | Type | Description |
|---|---|---|
| itemsreq | CheckRequest[] | - |
Response
| Field | Type | Description |
|---|---|---|
| resultsreq | CheckResponse[] | - |
| summaryreq | BatchSummary | - |
Errors
- 400: Invalid request: missing input, or a batch over the cap.
- 401: Missing or revoked API key.
- 403: Publishable key used from an Origin not on its allowlist.
- 429: Rate limit exceeded; retry after the Retry-After header.
Schemas
The request and response objects, as the API returns them.
BatchRequest
| Field | Type | Description |
|---|---|---|
| itemsreq | CheckRequest[] | - |
BatchResponse
| Field | Type | Description |
|---|---|---|
| resultsreq | CheckResponse[] | - |
| summaryreq | BatchSummary | - |
BatchSummary
| Field | Type | Description |
|---|---|---|
| countreq | integer | - |
CheckRequest
| Field | Type | Description |
|---|---|---|
| string | Email address to check. | |
| domain | string | Bare domain to check. |
CheckResponse
| Field | Type | Description |
|---|---|---|
| checkedreq | boolean | Whether the address was actually evaluated. False on a safe fail-open response (for example over quota or an inactive subscription); when false, treat the result as allow and ignore the signals. |
| normalized_email | string | The submitted email, trimmed and lowercased. Null when only a domain was sent. |
| domain | string | The domain that was checked. |
| disposable | boolean | The core verdict: true when the domain belongs to a disposable or throwaway email provider. Null when the address was not checked. |
| mx_valid | boolean | Whether the domain has valid mail-exchange (MX) records and can receive mail. DNS-level only; no mailbox is ever probed. |
| role_account | boolean | Whether the local part is a role address (for example info@, support@, admin@) rather than a person. |
| relay | boolean | Whether the domain is a forwarding or relay or alias-masking provider. |
| public_domain | boolean | Whether the domain is a public consumer mailbox provider (for example gmail.com). |
| spam_risk | boolean | Whether the domain appears on a spam or abuse reputation list. Opt-in, off by default, and never affects the core disposable verdict. |
| did_you_mean | string | A suggested correction when the domain looks like a typo of a common provider (for example gmial.com for gmail.com), or null. |
| mx_records | string[] | The resolved MX hostnames, or an empty list when there are none. Null on a fail-open response (when checked is false). |
| actionreq | string | The recommended action for this result under the account's enforcement policy: one of allow, warn, or block. The platform never blocks on your behalf; your snippet or caller applies it. |
| reason | string | A short code explaining the action or verdict. Examples: disposable, mx_invalid, relay, role_account, public_domain, spam_risk (the signal that fired), dns_unavailable, quota_exceeded, subscription_inactive, account_blocklist, account_allowlist. Treat unknown codes gracefully, since the set can grow. Null when no specific reason applies. |
ErrorDetail
| Field | Type | Description |
|---|---|---|
| reasonreq | string | - |
| message | string | - |
ErrorResponse
| Field | Type | Description |
|---|---|---|
| detailreq | ErrorDetail | - |
Snippet install guide
Drop one tag into your page. It watches your email fields and checks them as the visitor types, enforcing the mode you choose. No build step.
<script src="https://cdn.isitdisposable.com/v1/snippet.js"
data-key="pk_live_…"
data-mode="warn"
async></script>Attributes
| Attribute | Purpose | Default |
|---|---|---|
| data-key | Your account publishable key (pk_...) | required |
| data-mode | block, warn, or flag (flag only sets a hidden field and fires the callback) | warn |
| data-selector | Which fields to watch | all email inputs |
| data-message | Message shown on warn or block | a sensible default |
| data-callback | Global function called with the full result | none |
| data-debounce | Milliseconds to wait after typing | 600 |
The dashboard generates a snippet pre-filled with your publishable key under Snippet.
Errors
Errors return a JSON (JavaScript Object Notation) body of the shape { detail: { reason, message } }. A 429 includes a Retry-After header. Detection problems never raise an error; they fail open with an allow.
Rate limits are per second and depend on your plan; see pricing.
For AI agents
Point your agent or client generator at the machine-readable specification. It is the same schema this page is built from, scoped to the public endpoints:
GET https://api.isitdisposable.com/v1/openapi.json