The WhatsApp Business check answers two questions about a phone number: does it have a WhatsApp account, and is that account a WhatsApp Business account? You get registered (true, false or unknown) plus a business flag, with the time we checked. It works worldwide, in real time and in bulk jobs, and never returns profile details.
How can you tell if a WhatsApp number is a business account?
There are two ways: look in the app for one chat, or check the number through the API.
- In the app. Open the chat and tap the name at the top. A business account opens a business profile with whatever details the business chose to add, instead of a personal profile. Some businesses also show a Meta Verified badge, which "means a business has registered their information with Meta" (Meta, 6 June 2024). Most business accounts have no badge, so its absence says little.
- Through the API. Send the number with the check
whatsapp.business. You getregistered(true, false or unknown) andattributes.business(true for a business account, false for a regular one), without opening a chat or saving the number. For a list, run it as a bulk job.
Either way, a business account shows how the account was set up, not who owns it. Anyone can install the WhatsApp Business app.
What does the WhatsApp Business check tell you?
It reports whether a WhatsApp account is associated with the number and, if so, whether it was set up as a business account. WhatsApp launched the separate WhatsApp Business app for small businesses in January 2018 (WhatsApp blog). Larger companies reach customers through the WhatsApp business platform instead. Either way, a number carries one WhatsApp account at a time, so a business number is not also a personal account.
registered: trueandattributes.business: true: a WhatsApp Business account exists.registered: trueandbusiness: false: a regular WhatsApp account exists.registered: trueandbusiness: null: an account exists, but the business flag could not be determined this time.registered: false: conclusive answer, no account.registered: null: unknown, not charged.
The flag describes how the account is configured. It says nothing about who owns the number or whether the business is genuine.
Who uses it, and why?
The business flag helps where the difference between a consumer and a company matters.
- B2B lead verification. A sales lead that gives a company mobile number with a business account on WhatsApp is consistent with its claim. A lead claiming to be a company with no account at all may deserve a closer look. See lead verification.
- Marketplace and merchant onboarding. Platforms that onboard sellers, drivers or service providers can record whether the contact number is run as a business account, as one input to their review.
- Impersonation and fraud review. Scammers often pose as a company's support line. Knowing whether a number that contacted your customers is a business account helps a fraud team decide how to triage reports, together with a spam reputation check where it is available.
- Channel planning for consented messages. Messages from your own business account to a customer's business account behave like any other WhatsApp chat, but many businesses route business contacts to e-mail or account managers instead. Agencies cleaning client lists before a campaign can follow WhatsApp list hygiene for marketing agencies.
What do you get back?
One result per number in checks["whatsapp.business"]. The older top-level whatsapp object mirrors it and adds a business field, so v1 integrations keep working.
| Field | Type | Meaning |
|---|---|---|
registered | boolean or null | true account exists, false no account, null unknown |
attributes.business | boolean | true business account, false regular account; absent when not determined |
status | enum | completed, pending, unknown, unsupported_country or failed |
confidence / confidence_score | enum / 0–1 | How sure the registration answer is |
checked_at | timestamp | When the answer was obtained |
cached / age_seconds / billed | boolean / integer / boolean | Cache and billing details for this check |
reason | string or null | Why an answer is not conclusive |
whatsapp.business | boolean or null | Same flag in the v1 shape; null when not determined |
If you request whatsapp and whatsapp.business together, the two collapse into whatsapp.business, because it answers both.
How is it billed?
You pay per number, for conclusive answers only. You're not charged for inconclusive results (unknown, unsupported country, timeout, invalid, duplicate). A result with a conclusive registered value counts as conclusive even when business is null. The business check has its own real-time and bulk prices, which differ from the plain registration check, so see pricing for current rates. In a bulk job, the bulk price applies to groups of at least 132 numbers from the same country; smaller groups are checked the real-time way and priced at the real-time price, as the free job estimate shows before the job runs (see bulk jobs).
Repeat checks of the same number within the freshness window can be answered from your account's cache for free (cached: true, billed: false). Send max_age: 0 to force a fresh, billed check, and max_cost to cap what a request may cost.
What are the limits?
The check runs in real time (POST /v1/lookup, up to 100 numbers per request) and in bulk jobs (POST /v1/jobs, up to 50,000 numbers and e-mails per job) for numbers in every country.
- The business flag is filled more reliably in bulk jobs. Real-time answers may return
business: nullnext to a conclusiveregisteredvalue. If the flag is essential, run the list as a job with at least 132 numbers per country (smaller groups are checked the real-time way). - Up to 20 checks per request; numbers × checks may not exceed 2,000 per lookup or 100,000 per job.
- Requests that look like sequential number ranges or generated e-mail lists are rejected (
suspected_enumeration). - A daily cap applies per account;
GET /v1/limitsshows what is left today.
How do I use it responsibly?
Check numbers you have a lawful reason to process: leads who contacted you, sellers applying to your platform, numbers reported to your fraud team. Don't use the flag to compile lists of businesses to message cold. Our acceptable use policy forbids unsolicited bulk messaging and range scanning, and WhatsApp's own business messaging rules require opt-in before a business messages someone. People whose numbers were checked can object via the opt-out form.
Example request
+447700900006 is the test number for a registered business account. The other test numbers behave as documented in test mode; for them business is false whenever the answer is conclusive.
curl https://api.mobilevalidate.com/v1/lookup \
-H "Authorization: Bearer mv_test_publicSandboxn9ZgneuhR1B9CRfKG3fulym" \
-H "Content-Type: application/json" \
-d '{"numbers":["+447700900006"],"checks":["whatsapp.business"]}'// npm install mobilevalidate · Node.js 20+ · save as check.mjs and run: node check.mjs
import { MobileValidate } from "mobilevalidate";
// Omit apiKey to read MOBILEVALIDATE_API_KEY from the environment.
const mv = new MobileValidate({ apiKey: "mv_test_publicSandboxn9ZgneuhR1B9CRfKG3fulym" });
const { data, error } = await mv.lookup({
numbers: ["+447700900006"],
checks: ["whatsapp.business"],
});
if (error) console.error(error.code, error.message);
else console.dir(data.results, { depth: null });// Node.js 18+, Deno, Bun or the browser console (ES module: save as .mjs or use "type": "module").
const res = await fetch("https://api.mobilevalidate.com/v1/lookup", {
method: "POST",
headers: {
Authorization: "Bearer mv_test_publicSandboxn9ZgneuhR1B9CRfKG3fulym",
"Content-Type": "application/json",
},
body: JSON.stringify({
numbers: ["+447700900006"],
checks: ["whatsapp.business"],
}),
});
console.log(res.status, res.headers.get("x-request-id"));
console.dir(await res.json(), { depth: null });# pip install mobilevalidate-sdk
from mobilevalidate import MobileValidate
# Omit api_key to read MOBILEVALIDATE_API_KEY from the environment.
mv = MobileValidate(api_key="mv_test_publicSandboxn9ZgneuhR1B9CRfKG3fulym")
result = mv.lookup(numbers=["+447700900006"], checks=["whatsapp.business"])
print(result)<?php
$ch = curl_init('https://api.mobilevalidate.com/v1/lookup');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer mv_test_publicSandboxn9ZgneuhR1B9CRfKG3fulym',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'numbers' => ['+447700900006'],
'checks' => ['whatsapp.business'],
]),
]);
$response = curl_exec($ch);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL, $response, PHP_EOL;package main
import (
"fmt"
"io"
"net/http"
"strings"
)
func main() {
body := strings.NewReader(`{"numbers":["+447700900006"],"checks":["whatsapp.business"]}`)
req, err := http.NewRequest("POST", "https://api.mobilevalidate.com/v1/lookup", body)
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "Bearer mv_test_publicSandboxn9ZgneuhR1B9CRfKG3fulym")
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
out, _ := io.ReadAll(res.Body)
fmt.Println(res.Status, string(out))
}require "net/http"
require "json"
uri = URI("https://api.mobilevalidate.com/v1/lookup")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer mv_test_publicSandboxn9ZgneuhR1B9CRfKG3fulym"
req["Content-Type"] = "application/json"
req.body = JSON.generate({
"numbers" => ["+447700900006"],
"checks" => ["whatsapp.business"]
})
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
puts res.code, res.bodyRuns as pasted with the public sandbox key, which answers the test values only. In the SDKs, omit the key to use MOBILEVALIDATE_API_KEY.
Response (excerpt, test mode: the first item of results):
{
"kind": "phone",
"input": "+447700900006",
"e164": "+447700900006",
"country": "GB",
"number_status": "valid",
"checks": {
"whatsapp.business": {
"service": "whatsapp.business",
"status": "completed",
"registered": true,
"attributes": {
"business": true
},
"confidence": "high",
"confidence_score": 0.99,
"checked_at": "2026-09-25T14:25:29.519Z",
"cached": false,
"age_seconds": 0,
"billed": false,
"reason": null,
"poll_after_ms": null
}
},
"whatsapp": {
"service": "whatsapp.business",
"status": "completed",
"registered": true,
"confidence": "high",
"confidence_score": 0.99,
"checked_at": "2026-09-25T14:25:29.519Z",
"cached": false,
"age_seconds": 0,
"billed": false,
"reason": null,
"poll_after_ms": null,
"business": true
},
"test": true
}Try it now
Run it here with a test value: the console calls the live API from your browser with the public sandbox key and shows the real JSON and a plain-English verdict.
POST /v1/lookup
Public sandbox key · test values only · never billed
Pick a test value or press Run
Press Run or pick a test value above: the console sends a real request to the API with the public sandbox key and shows the answer here.
No response body.curl https://api.mobilevalidate.com/v1/lookup \
-H "Authorization: Bearer mv_test_publicSandboxn9ZgneuhR1B9CRfKG3fulym" \
-H "Content-Type: application/json" \
-d '{"numbers":["+447700900001"],"checks":["whatsapp.business"]}'Check your own numbers: 20 phone numbers and 10 e-mail addresses are checked for real, free, after sign-up. Start free
checks: ["whatsapp.business"] · Realtime lookup via POST /v1/lookup. Every example runs as pasted: it uses the public sandbox key, which answers the test values for free. In the SDKs, omit the key to use MOBILEVALIDATE_API_KEY.
curl https://api.mobilevalidate.com/v1/lookup \
-H "Authorization: Bearer mv_test_publicSandboxn9ZgneuhR1B9CRfKG3fulym" \
-H "Content-Type: application/json" \
-d '{"numbers":["+447700900001"],"checks":["whatsapp.business"]}'// npm install mobilevalidate · Node.js 20+ · save as check.mjs and run: node check.mjs
import { MobileValidate } from "mobilevalidate";
// Omit apiKey to read MOBILEVALIDATE_API_KEY from the environment.
const mv = new MobileValidate({ apiKey: "mv_test_publicSandboxn9ZgneuhR1B9CRfKG3fulym" });
const { data, error } = await mv.lookup({
numbers: ["+447700900001"],
checks: ["whatsapp.business"],
});
if (error) console.error(error.code, error.message);
else console.dir(data.results, { depth: null });// Node.js 18+, Deno, Bun or the browser console (ES module: save as .mjs or use "type": "module").
const res = await fetch("https://api.mobilevalidate.com/v1/lookup", {
method: "POST",
headers: {
Authorization: "Bearer mv_test_publicSandboxn9ZgneuhR1B9CRfKG3fulym",
"Content-Type": "application/json",
},
body: JSON.stringify({
numbers: ["+447700900001"],
checks: ["whatsapp.business"],
}),
});
console.log(res.status, res.headers.get("x-request-id"));
console.dir(await res.json(), { depth: null });# pip install mobilevalidate-sdk
from mobilevalidate import MobileValidate
# Omit api_key to read MOBILEVALIDATE_API_KEY from the environment.
mv = MobileValidate(api_key="mv_test_publicSandboxn9ZgneuhR1B9CRfKG3fulym")
result = mv.lookup(numbers=["+447700900001"], checks=["whatsapp.business"])
print(result)<?php
$ch = curl_init('https://api.mobilevalidate.com/v1/lookup');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer mv_test_publicSandboxn9ZgneuhR1B9CRfKG3fulym',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'numbers' => ['+447700900001'],
'checks' => ['whatsapp.business'],
]),
]);
$response = curl_exec($ch);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL, $response, PHP_EOL;package main
import (
"fmt"
"io"
"net/http"
"strings"
)
func main() {
body := strings.NewReader(`{"numbers":["+447700900001"],"checks":["whatsapp.business"]}`)
req, err := http.NewRequest("POST", "https://api.mobilevalidate.com/v1/lookup", body)
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "Bearer mv_test_publicSandboxn9ZgneuhR1B9CRfKG3fulym")
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
out, _ := io.ReadAll(res.Body)
fmt.Println(res.Status, string(out))
}require "net/http"
require "json"
uri = URI("https://api.mobilevalidate.com/v1/lookup")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer mv_test_publicSandboxn9ZgneuhR1B9CRfKG3fulym"
req["Content-Type"] = "application/json"
req.body = JSON.generate({
"numbers" => ["+447700900001"],
"checks" => ["whatsapp.business"]
})
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
puts res.code, res.body// .mcp.json (Claude Code), ~/.cursor/mcp.json (Cursor) or .vscode/mcp.json ("servers" instead of "mcpServers")
{
"mcpServers": {
"mobilevalidate": {
"type": "http",
"url": "https://mcp.mobilevalidate.com/mcp",
"headers": { "Authorization": "Bearer ${MOBILEVALIDATE_API_KEY}" }
}
}
}
// Then ask your agent, e.g.:
// "Check +447700900001 with whatsapp.business" → tool: lookup_numbersThe hosted MCP server is live for customers with an agent key (mv_agent_…) or a test key. Or run it locally with npx -y @mobilevalidate/mcp.
Real test-mode result for this check
{
"service": "whatsapp.business",
"status": "completed",
"registered": true,
"attributes": {
"business": false
},
"confidence": "high",
"confidence_score": 0.99,
"checked_at": "2026-09-25T14:25:28.979Z",
"cached": false,
"age_seconds": 0,
"billed": false,
"reason": null,
"poll_after_ms": null
}What you get
Fields of checks["whatsapp.business"], generated from the public service catalog.
| Field | Type | Meaning |
|---|---|---|
| registered | boolean | null | true = found, false = not found, null = unknown (not charged). |
| status | enum | completed, pending, unknown, unsupported_country or failed. |
| checked_at | timestamp | When the answer was obtained. |
| attributes.business | boolean | Account is a WhatsApp Business account. |
Frequently asked questions
How can you tell if a WhatsApp number is a business account?
In the app, open the chat and tap the name at the top: a business account opens a business profile, and some businesses carry a verified badge. For numbers you can't open one by one, the whatsapp.business check returns registered plus a business flag per number, in real time or in bulk.
What is the difference between a WhatsApp account and a WhatsApp Business account?
Both are tied to one phone number. A WhatsApp Business account is created with the separate WhatsApp Business app or through the WhatsApp business platform, and it can show a business profile. This check reports registration and, separately, whether the account is a business account.
Why is business null when registered is true?
The account check was conclusive but the business flag could not be determined for that answer. This happens more often on real-time lookups. The answer is still a conclusive registration result.
Do I need to request whatsapp and whatsapp.business together?
No. The business check already answers whether an account exists. If you request both, the API runs only whatsapp.business and you pay for one check per number.
Does a business account prove that a number belongs to a real company?
No. Anyone can install the WhatsApp Business app, so the flag says how the account was set up, not who owns it. Treat it as one signal next to your own verification steps.
Is the business name or profile returned?
No. The result contains only registered and the business flag. Names, photos, descriptions and other profile details are never returned.
Is there a free whatsApp Business account check?
Yes, to try it on your own data: create a free account and check up to 20 phone numbers for real on the dashboard's Try it page, at no cost. Test mode with documented test values is free and unlimited. After that, a whatsApp Business account check costs $0.004 per check in real time ($4.00 per 1,000) and $0.0003 in bulk jobs ($0.30 per 1,000), paid from prepaid credit. Unknown and other inconclusive results are always free.

