Validate email addresses, phone numbers, and IP addresses with a single endpoint. One credit per lookup.
The VerifyGrid API is a single POST endpoint that accepts an email address, phone number, or IP address and returns validation signals. The type is auto-detected, or you can specify it explicitly. Each lookup consumes one credit from the API key used; lookups that fail on our side are not charged.
1. Create an API key
Open the dashboard and click “New key” to generate a key. Copy it — you won't be able to see it later if you lose it.
2. Send your first request
POST to the validate endpoint with your key and a value to validate.
3. Read the result
The response includes a valid flag and type-specific signals you can route on.
Authenticate every request with your API key. Pass it in the request body as api_key, or as the x-api-key header. Sign in to the dashboard to create keys, and verify a mobile number there to unlock 100 free trial credits.
x-api-key: YOUR_API_KEYPOST https://verifygrid95.base44.app/functions/validate
Request body parameters:
| Parameter | Type | Description |
|---|---|---|
| value | string | The email, phone, or IP to validate. Required unless you send values. |
| values | string[] | Batch mode: up to 100 values to validate in one request. See Batch requests. |
| api_key | string | Your key. Alternatively send the x-api-key header. |
| type | string | Optional. 'email' | 'phone' | 'ip'. Auto-detected per value if omitted. |
| country | string | Optional. ISO-2 country for phone numbers written without a +country code. Defaults to US. |
{
"value": "+44 20 7946 0958",
"api_key": "YOUR_API_KEY"
}A successful response returns the detected type, the echoed value, a result object, and credits_remaining. Every result includes valid, fraud_score and risk_reasons, plus decision (allow, review, or block, from your rules) and decision_reasons. The other fields vary by type. A field is left out when no data is available for it.
fraud_score is a 0–100 risk score (lower is safer) built from the signals in the result, such as a disposable domain, a VoIP line, or a VPN. Each signal that adds to the score is listed in risk_reasons.
Checks the address syntax and looks up the domain’s mail servers live over DNS. We don’t connect to mail servers to probe individual mailboxes.
| valid | boolean | Syntax is valid and the domain has a mail server. |
| deliverability | string | high: MX records found · medium: no MX, but the domain has an address mail can fall back to · low: domain can't receive mail. |
| mx_found | boolean | Whether the domain publishes MX records. |
| is_disposable | boolean | Domain is on a maintained blocklist of throwaway / temporary email providers. |
| is_role_account | boolean | Address is a shared role inbox such as info@ or support@. |
| is_free_provider | boolean | Domain is a free consumer provider such as gmail.com. |
| did_you_mean | string | Suggested correction when the domain looks like a typo, e.g. gmial.com. |
| domain | string | The normalized domain that was checked. |
Phone
Validated against Google’s libphonenumber numbering-plan data. Where live carrier data is available, the carrier name and the number’s current line type come from a carrier lookup.
| valid | boolean | The number is assigned in its country's numbering plan. |
| e164 | string | The number in E.164 format, e.g. +442079460958. |
| international_format | string | Human-readable international format. |
| country | string | ISO-2 country code. |
| line_type | string | mobile | landline | landline_or_mobile | voip | toll_free | premium_rate | shared_cost | personal | pager | uan | voicemail | unknown |
| line_type_source | string | carrier_lookup (live) or numbering_plan (from the number's prefix range). |
| is_voip | boolean | Whether the line is VoIP. |
| carrier | string | Carrier name, when live carrier data is available. |
IP
IPv4 and IPv6. Private and reserved addresses are recognized locally; public addresses get a live lookup.
| valid | boolean | Whether the value is a valid IPv4 or IPv6 address. |
| ip | string | The normalized address. |
| version | string | ipv4 | ipv6 |
| is_public | boolean | False for private, loopback, and reserved ranges (then ip_range names the range). |
| country | string | ISO-2 country code. |
| region / city | string | Approximate location. |
| asn | string | Autonomous system number, e.g. AS24940. |
| isp | string | Network provider. |
| connection_type | string | e.g. residential, business, wireless, hosting, vpn, tor. |
| is_proxy | boolean | Any anonymizing proxy, including VPNs and Tor. |
| is_vpn | boolean | A VPN exit was detected. |
| is_tor | boolean | A Tor exit node was detected. |
| is_hosting | boolean | The address belongs to a hosting / data-center network. |
{
"type": "email",
"value": "sarah.chen@gmial.com",
"result": {
"valid": false,
"deliverability": "low",
"mx_found": false,
"is_disposable": true,
"is_role_account": false,
"is_free_provider": false,
"domain": "gmial.com",
"did_you_mean": "sarah.chen@gmail.com",
"fraud_score": 100,
"risk_reasons": [
"domain DNS is failing",
"disposable email domain",
"possible typo of gmail.com"
]
},
"credits_remaining": 99
}Send values instead of value to validate up to 100 items in one request. Each item can be a different type. Results come back in the same order. The key must hold enough credits for the whole batch up front; any item that fails on our side is refunded.
{
"values": ["sarah.chen@techcorp.io", "+44 20 7946 0958", "203.0.113.42"],
"api_key": "YOUR_API_KEY"
}{
"results": [
{ "type": "email", "value": "sarah.chen@techcorp.io", "result": { "valid": true, ... } },
{ "type": "phone", "value": "+44 20 7946 0958", "result": { "valid": true, ... } },
{ "value": "203.0.113.42", "error": "lookup temporarily unavailable; no credit was charged" }
],
"credits_used": 2,
"credits_remaining": 97
}Check a whole signup in one call. Send any of email, phone, and ip (plus an optional country for phone numbers without a + code) and get back one decision. It costs 1 credit per field you send; a check that fails on our side is refunded and the decision is made from the others.
POST https://verifygrid95.base44.app/functions/signup-check
{
"email": "support@mailinator.com",
"phone": "+44 20 7946 0958",
"ip": "185.220.101.1",
"api_key": "YOUR_API_KEY"
}| decision | string | allow | review | block, from your rules. |
| risk_score | number | Combined 0–100 score: the riskiest check, +10 for each other risky check, +15 when the phone and IP countries differ. |
| decision_reasons | string[] | Why the decision was made (rule, list, country, or threshold). |
| risk_reasons | string[] | Every risk signal, prefixed with its check, e.g. email: disposable email domain. |
| score_notes | string[] | Points added by combining the checks. |
| signals | string[] | Signal names that fired, as used in rules (e.g. disposable_email, tor). |
| checks | object | The full email, phone, and ip results, same fields as the validate endpoint. |
| credits_used | number | Credits charged for this call. |
Every result carries a decision from your account’s rules, which you edit under Rules in the dashboard. The defaults are: block invalid values, block at a risk score of 70 or more, review at 30 or more, allow the rest. Rules are applied in this order:
disposable_email, voip_phone, vpn, or tor, to review or block), the allowed countries rule, and your review / block thresholds.value is required / values may contain at most 100 items / type must be one of email, phone, ip
The request body is missing or malformed.
api_key is required / invalid or revoked api key
Missing, unknown, or revoked key.
insufficient credits
The key doesn't have enough credits for the request. Buy more on the Pricing page.
lookup temporarily unavailable; no credit was charged
A data source didn't respond. Safe to retry.
internal error
Something went wrong on our side. Retry or contact us.
cURL
curl -X POST https://verifygrid95.base44.app/functions/validate \
-H "Content-Type: application/json" \
-d '{
"value": "sarah.chen@techcorp.io",
"api_key": "YOUR_API_KEY"
}'JavaScript (fetch)
const res = await fetch("https://verifygrid95.base44.app/functions/validate", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
value: "203.0.113.42",
api_key: process.env.VERIFYGRID_KEY
})
});
const data = await res.json();
console.log(data.result);Python
import requests, os
resp = requests.post("https://verifygrid95.base44.app/functions/validate", json={
"value": "+44 7700 900123",
"api_key": os.environ["VERIFYGRID_KEY"]
})
print(resp.json()["result"])No code needed: open List cleaning in the dashboard, upload a CSV of up to 25,000 rows, pick the column to check, and download the same file with these columns added to every row: vg_status, vg_risk_score, vg_risk_level, vg_action (allow, review, or block), vg_reasons, and type-specific fields such as vg_disposable or vg_line_type. Each distinct value costs one credit; duplicates and empty cells are free. The file is read in your browser and only the chosen column is sent.
API keys are managed in the dashboard — there is no REST endpoint for creating or revoking keys. Create separate keys per environment, keep them in a secrets manager, and revoke any key that may be exposed.
Go to dashboard