API v2 (beta)
Number checks
A number check finds out which phone numbers have a WhatsApp account, without sending them anything. Clean a list before a campaign, or check a sign-up's number before you message it. Checks made with the API are the same as the lists on the Number verification page of the dashboard.
| Operation | Endpoint | Scope |
|---|---|---|
| Start a check | POST /api/v2/number-checks | contacts |
| List checks | GET /api/v2/number-checks | contacts |
| Get a check | GET /api/v2/number-checks/{id} | contacts |
| Get the results | GET /api/v2/number-checks/{id}/results | contacts |
Starting a check needs a plan that includes number verification; otherwise it answers 403 plan_required. Reading checks works on any plan.
Start a check#
https://wbiztool.com/api/v2/number-checksBody: JSON (application/json)
The numbers are queued, and the answer is 201 with the check in status pending. A connected WhatsApp number of your workspace checks them over the next minutes. Poll the check until status is completed, then read the results.
Body
numbersarray of stringsrequiredThe numbers to check, 1 to 10,000 entries. Write them in international format with
+(+919876543210). A number without its country code gets the workspace's. Repeats are checked once, and entries that aren't phone numbers are skipped.namestringoptionalA name for the check, up to 500 characters, as shown on the Number verification page. Default:
API checkand the date and time in UTC, such asAPI check 2026-10-18 10:40.
curl -X POST https://wbiztool.com/api/v2/number-checks \
-H "Authorization: Bearer $WBIZTOOL_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: october-leads" \
-d '{
"name": "October leads",
"numbers": ["+919876543210", "+447700900123", "+14155550123"]
}'import os
import time
import requests
API = "https://wbiztool.com/api/v2"
headers = {"Authorization": f"Bearer {os.environ['WBIZTOOL_API_KEY']}"}
check = requests.post(f"{API}/number-checks", headers=headers, timeout=60, json={
"name": "October leads",
"numbers": ["+919876543210", "+447700900123", "+14155550123"],
}).json()
print("Skipped entries:", check["skipped"])
while check["status"] != "completed":
time.sleep(30)
check = requests.get(f"{API}/number-checks/{check['id']}", headers=headers, timeout=30).json()
print(check["counts"])
params = {"limit": 100}
while True:
page = requests.get(f"{API}/number-checks/{check['id']}/results",
headers=headers, params=params, timeout=30).json()
for result in page["data"]:
print(result["number"], result["status"])
if not page["next_cursor"]:
break
params["cursor"] = page["next_cursor"]// Node.js 18+ (built-in fetch). Save as .mjs to use top-level await.
const API = "https://wbiztool.com/api/v2";
const headers = { Authorization: `Bearer ${process.env.WBIZTOOL_API_KEY}`, "Content-Type": "application/json" };
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
let check = await (await fetch(`${API}/number-checks`, {
method: "POST",
headers,
body: JSON.stringify({ name: "October leads", numbers: ["+919876543210", "+447700900123", "+14155550123"] }),
})).json();
while (check.status !== "completed") {
await sleep(30000);
check = await (await fetch(`${API}/number-checks/${check.id}`, { headers })).json();
}
const params = new URLSearchParams({ limit: "100" });
while (true) {
const page = await (await fetch(`${API}/number-checks/${check.id}/results?${params}`, { headers })).json();
for (const result of page.data) console.log(result.number, result.status);
if (!page.next_cursor) break;
params.set("cursor", page.next_cursor);
}<?php
$ch = curl_init('https://wbiztool.com/api/v2/number-checks');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('WBIZTOOL_API_KEY'), 'Content-Type: application/json'],
CURLOPT_POSTFIELDS => json_encode([
'name' => 'October leads',
'numbers' => ['+919876543210', '+447700900123', '+14155550123'],
]),
CURLOPT_RETURNTRANSFER => true,
]);
$check = json_decode(curl_exec($ch), true);
curl_close($ch);
// Save $check['id'], then poll GET /api/v2/number-checks/{id} until status is completed.
echo $check['id'] . ' ' . $check['status'] . ' skipped: ' . $check['skipped'];Answer (201):
{
"id": 51207,
"name": "October leads",
"status": "pending",
"counts": { "total": 3, "pending": 3, "on_whatsapp": 0, "not_on_whatsapp": 0, "cancelled": 0 },
"created_at": "2026-10-18T10:40:02.511Z",
"skipped": 0
}
skipped is how many entries weren't a phone number (text, fewer than 7 or more than 15 digits): they aren't checked and don't count toward your plan.
Plan limits#
Your plan sets how many numbers you can check (see Plan limits):
- Per check: a check can't have more numbers than the plan's number. Over it, the check is refused with
too_many_numbers, withcountandlimit. - Per billing period: all checks together, from the API and the dashboard, can't go over it either. A check that would go over is refused with
number_check_quota_reached, withrequested,usedandlimit. - A plan without a limit has neither. The API takes at most 10,000 numbers per request whatever the plan.
- A refused check queues nothing. Split the list, wait for the next period, or upgrade.
Errors when starting a check#
| HTTP | Code | When |
|---|---|---|
400 | validation_failed | numbers is missing, empty or not a list of strings, or name is empty or too long |
403 | plan_required | The plan doesn't include number verification |
422 | no_valid_numbers | None of the entries is a phone number; skipped says how many there were |
422 | too_many_numbers | More than 10,000 entries, or more numbers than the plan allows per check |
422 | number_check_quota_reached | The check would go over the plan's numbers for this billing period |
List checks#
https://wbiztool.com/api/v2/number-checksThe workspace's checks, newest first, in pages (limit 1 to 100, default 25, and cursor), including those started in the dashboard. Each is a Number check.
curl https://wbiztool.com/api/v2/number-checks \
-H "Authorization: Bearer $WBIZTOOL_API_KEY"
Get a check#
https://wbiztool.com/api/v2/number-checks/{id}The check and its progress. Poll it every 30 seconds or so until status is completed.
curl https://wbiztool.com/api/v2/number-checks/51207 \
-H "Authorization: Bearer $WBIZTOOL_API_KEY"
{
"id": 51207,
"name": "October leads",
"status": "processing",
"counts": { "total": 3, "pending": 1, "on_whatsapp": 1, "not_on_whatsapp": 1, "cancelled": 0 },
"created_at": "2026-10-18T10:40:02.511Z"
}
A check that doesn't exist answers 404 number_check_not_found.
Checking needs a WhatsApp number of the workspace connected by QR code or pairing code, and waits while your numbers are sending. A check can stay pending or processing for a while; see How checking works.
Get the results#
https://wbiztool.com/api/v2/number-checks/{id}/resultsThe check's numbers and what was found, in pages (limit 1 to 100, default 25, and cursor). You can read them while the check runs: numbers not checked yet are pending.
curl "https://wbiztool.com/api/v2/number-checks/51207/results?limit=100" \
-H "Authorization: Bearer $WBIZTOOL_API_KEY"
{
"data": [
{ "number": "14155550123", "on_whatsapp": null, "status": "pending", "checked_at": null },
{ "number": "447700900123", "on_whatsapp": false, "status": "not_on_whatsapp", "checked_at": "2026-10-18T10:42:57.204Z" },
{ "number": "919876543210", "on_whatsapp": true, "status": "on_whatsapp", "checked_at": "2026-10-18T10:42:51.880Z" }
],
"next_cursor": null
}
| Field | Type | Description |
|---|---|---|
number | string | The number checked: its digits with the country code, no +. |
on_whatsapp | boolean or null | true or false once checked; null while pending or when cancelled. |
status | string | pending, on_whatsapp, not_on_whatsapp or cancelled (stopped before it was checked). |
checked_at | string or null | When it was checked. |
The Number check object#
| Field | Type | Description |
|---|---|---|
id | integer | The check's id. |
name | string | Its name. |
status | string | pending (nothing checked yet), processing (some checked) or completed (none left to check). |
counts | object | total, pending, on_whatsapp, not_on_whatsapp and cancelled. |
created_at | string | When it was started. |
skipped | integer | Only in the answer to Start a check: entries that weren't a phone number. |
Related#
- Number verification in the dashboard
- Plans and billing
- Errors
