Authentication
Every request needs an API key in the x-api-key header. Generate one from Settings → API keys in your dashboard — the raw key is shown once, at creation, so copy it before closing the dialog.
curl https://wavalid.com/api/v1/validate \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"phoneNumber": "+14155551234"}'Requests without a valid key, or with a revoked one, get back 401 Unauthorized. A rate-limited request gets 429 Too Many Requests instead — see Rate limits.
Base URL
https://wavalid.com/api/v1
All endpoints below are relative to this base URL.
Validate a number
POST /validate
Checks a single phone number and deducts one credit if the check completes.
Body
| Field | Type | Required | Description |
|---|---|---|---|
phoneNumber | string | Yes | E.164 international format, e.g. +14155551234. Must include the country code. |
batchId | number | No | Group this check under an existing batch. Omit it and a default batch is used. |
Response
{
"phoneNumber": "+14155551234",
"status": "valid",
"creditsRemaining": 482
}status is one of:
| Status | Meaning |
|---|---|
valid | The number is registered and active on WhatsApp. |
invalid | The number is not on WhatsApp. |
limit | The check itself hit a provider limit. No credit is deducted. |
Example
curl https://wavalid.com/api/v1/validate \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"phoneNumber": "+14155551234"}'const response = await fetch("https://wavalid.com/api/v1/validate", {
method: "POST",
headers: {
"x-api-key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({ phoneNumber: "+14155551234" }),
});
const result = await response.json();Validate numbers in bulk
POST /validate/bulk
Checks up to 100 numbers in one request and deducts one credit per number checked.
Body
| Field | Type | Required | Description |
|---|---|---|---|
phoneNumbers | string[] | Yes | 1 to 100 numbers, each in E.164 format. |
batchId | number | No | Group these checks under an existing batch. Omit it and a default batch is used. |
Response
{
"results": [
{ "phoneNumber": "+14155551234", "status": "valid" },
{ "phoneNumber": "+442071838750", "status": "invalid" }
],
"creditsUsed": 2,
"creditsRemaining": 480
}Example
curl https://wavalid.com/api/v1/validate/bulk \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"phoneNumbers": ["+14155551234", "+442071838750"]}'Rate limits
Each API key allows 60 requests per minute. A request over that limit returns 429 Too Many Requests, with a Retry-After header (in seconds) telling you when to try again.
Credits are a separate limit from rate limiting: running out of credits fails a request even if you're well under the rate limit.
Errors
Application errors come back as JSON with a statusCode, a human-readable message, and — where applicable — a stable code you can match on:
{
"statusCode": 402,
"message": "You don't have enough credits to validate a number.",
"code": "insufficientCredits"
}A 400 is different: it means the request body itself failed validation, and the response instead lists what's wrong per field:
{
"success": false,
"error": [
{
"path": ["phoneNumber"],
"message": "Phone number must be in international format, e.g. +14155551234."
}
]
}| Status | When it happens |
|---|---|
400 | The request body failed validation — check phoneNumber formatting or array length. |
401 | The API key is missing, invalid, or revoked. |
402 | Your account doesn't have enough credits for the request. |
404 | The batchId you passed doesn't exist, or doesn't belong to your account. |
429 | You've exceeded the rate limit — see Rate limits. |