Skip to content
API reference

Email verification API — v1

Plain REST. JSON in, JSON out. Every credit works against the API — no separate plan, no per-endpoint surcharge.

Introduction

The Cleanify API runs at https://my.cleanify.io/api/v1 over HTTPS only. All requests return JSON. Every credit in your account works against the API — there is no separate API plan.

Authentication

Generate an API key from the API section of the dashboard sidebar. Name the token and assign the permissions you need — each token is scoped and revocable. Pass the token as a Bearer credential on every request.

curl https://my.cleanify.io/api/v1/ping \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <api_key>"
Keep keys secret. They act as a unique identifier for your account and give full access to your credits. Rotate from the dashboard if you suspect a leak; old keys are revoked immediately.

Your first request

Verify a single email address. Pass the address as a URL-encoded query parameter:

curl 'https://my.cleanify.io/api/v1/verify?email=hello%4050saas.com' \
  -H "Accept: application/json" \
  -H "Authorization: Bearer <api_key>"
{
  "success":      true,
  "email":        "hello@50saas.com",
  "result":       "deliverable",
  "reason":       "accept_all",
  "did_you_mean": null,
  "type": {
    "is_disposable":  false,
    "is_role":        true,
    "is_accept_all":  true,
    "is_free":        false
  }
}

Rate limits

Per-endpoint rate limits prevent runaway clients from starving shared capacity. A 429 response means you hit the ceiling — back off and retry after a few seconds.

EndpointRate limit
/api/v1/ping60 per minute
/api/v1/credits60 per minute
/api/v1/verify120 per minute
/api/v1/bulkverify5 per minute
/api/v1/check120 per minute
/api/v1/getresults30 per minute

Ping

Health probe. Returns pong when the entire verification pipeline is online.

GET /api/v1/ping
curl --location 'https://my.cleanify.io/api/v1/ping' \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer <api_key>'
{ "ping": "pong" }

Available credits

Returns the number of verification credits remaining on the account.

GET /api/v1/credits
curl --location 'https://my.cleanify.io/api/v1/credits' \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer <api_key>'
{
  "success": true,
  "credits": 49713
}

Quick verification

Validate a single email address synchronously. One credit per call. Pass the address as the email query parameter, URL-encoded.

GET /api/v1/verify

Query parameters

FieldTypeDescription
emailstringThe email address to verify. URL-encode the @ as %40. Required.

Example

curl --location 'https://my.cleanify.io/api/v1/verify?email=hello%4050saas.com' \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer <api_key>'
{
  "success":      true,
  "email":        "hello@50saas.com",
  "result":       "deliverable",
  "reason":       "accept_all",
  "did_you_mean": null,
  "type": {
    "is_disposable":  false,
    "is_role":        true,
    "is_accept_all":  true,
    "is_free":        false
  }
}

Bulk verification

Queue a bulk job. POST the list as a plain-text body, one address per line. Returns a requestId used by the status and results endpoints below.

POST /api/v1/bulkverify
curl --location 'https://my.cleanify.io/api/v1/bulkverify' \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer <api_key>' \
  --header 'Content-Type: text/plain' \
  --data-raw 'hello@50saas.com
sales@50saas.com
this.doesnt.exist.123@gmail.com'
{
  "success":   true,
  "requestId": "..."
}

Check bulk verification status

Poll for the progress of a bulk job. Use the requestId returned by /bulkverify.

POST /api/v1/check
curl --location 'https://my.cleanify.io/api/v1/check' \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer <api_key>' \
  --form 'requestId="..."'
{
  "success":    true,
  "total":      3,
  "percentage": 100,
  "status": {
    "deliverable":   1,
    "undeliverable": 0,
    "risky":         2,
    "unknown":       0,
    "duplicate":     0
  }
}

Bulk verification results

Fetch the grouped results once percentage reaches 100. Addresses are nested under their state, then their reason code.

POST /api/v1/getresults
curl --location 'https://my.cleanify.io/api/v1/getresults' \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer <api_key>' \
  --form 'requestId="..."'
{
  "success":    true,
  "total":      3,
  "percentage": 100,
  "status": {
    "deliverable":   1,
    "undeliverable": 0,
    "risky":         2,
    "unknown":       0,
    "duplicate":     0
  },
  "risky": {
    "low_deliverability": [
      {
        "email":             "test1@test.com",
        "state":             "risky",
        "reason":            "low_deliverability",
        "is_accept_all":     true,
        "is_disposable":     false,
        "is_free":           false,
        "is_mailbox_full":   false,
        "is_no_reply":       false,
        "is_role":           false,
        "is_mx_record":      "aspmx.l.google.com",
        "is_smtp_provider":  "Google"
      }
    ]
  },
  "deliverable": {
    "accepted_email": [
      {
        "email":             "test3@test.com",
        "state":             "deliverable",
        "reason":            "accepted_email",
        "is_accept_all":     false,
        "is_disposable":     false,
        "is_free":           true,
        "is_mailbox_full":   false,
        "is_no_reply":       false,
        "is_role":           false,
        "is_mx_record":      "gmail-smtp-in.l.google.com",
        "is_smtp_provider":  "Google"
      }
    ]
  }
}

Verification states & reasons

Every address resolves to one of five states. The reason field narrows the state with a specific cause — useful for segmenting a list.

Deliverable

We can determine with a high level of confidence that the email address is associated with a valid account.

ReasonMeaning
accepted_emailThe email address exists and is deliverable.

Undeliverable

We can determine with a high level of confidence that the email address is not associated with a valid account.

ReasonMeaning
invalid_emailThe email address does not pass syntax validations.
invalid_domainThe domain does not exist, is not valid, or should not be mailed to.
rejected_emailThe mail server rejected the address because it does not exist.
invalid_smtpThe mail server returned an unexpected or invalid response.

Risky

Emails seem to be deliverable but should be used with caution due to low quality or deliverability.

ReasonMeaning
low_qualityThe email address has quality issues that may make it risky or low value.
low_deliverabilityThe address appears to be deliverable, but deliverability cannot be guaranteed.

Unknown

The domain is not responding, meaning we cannot determine validity. Re-verify later — this state is not charged in bulk.

ReasonMeaning
no_connectCould not connect to the mail server.
timeoutMail server session or DNS query timed out.
unavailable_smtpThe mail server was unavailable to process our request at this time.
unexpected_errorAn unexpected error occurred.

Duplicate

The list contains more than one of the same email. Only the first occurrence is consumed; the rest are flagged and not recharged.

HTTP status codes

CodeStatusMeaning
249Try AgainYour request is taking longer than normal. Send the same request again.
400Bad RequestYour request is structured incorrectly.
401UnauthorizedYou did not send an API key.
402Payment RequiredYou don't have enough credits to complete this request.
403ForbiddenYour API key is invalid.
404Not FoundThe specified resource does not exist.
429Too Many RequestsYou're requesting an endpoint too often — see the rate-limits table above.
500Internal Server ErrorA server error occurred. Retry or contact support if it persists.
503Service UnavailableTemporarily offline for maintenance.