The MAX check tells you whether phone numbers have an account on MAX, a newer Russian messenger. It runs in bulk jobs, answers registered: true, false or null (unknown) per number, and returns nothing beyond that: no name, photo or profile. It is most relevant for Russian mobile numbers.
What does the MAX check tell you?
It answers whether a MAX account is associated with the number. MAX is a newer app, developed by the company behind the social network VK. It brings chats, calls and other everyday services into one app, and accounts are registered with a phone number confirmed by a code.
registered: true: a MAX account exists for the number.registered: false: a conclusive answer that there is none.registered: null: no conclusive answer; not charged.
Because the app is young and its user base is growing, answers for the same number can change faster than on long-established messengers. Read checked_at with every answer and keep max_age short if you rely on the result.
Who uses it, and why?
- Channel coverage for Russian customers. Messenger use in Russia is spread across several apps, including Telegram, WhatsApp and MAX. Businesses serving Russian customers check all three in one job to see which channel each opted-in customer can use. See channel selection.
- Contact-list hygiene. For lists of Russian numbers collected with consent, messenger presence is one way to tell live mobile numbers from stale ones.
- Tracking adoption in your own base. Product teams may want aggregate figures on how many of their existing customers have moved to a new messenger before they support it.
What do you get back?
Each job row carries checks["max.registered"]; the service has no extra attributes.
| Field | Type | Meaning |
|---|---|---|
registered | boolean or null | true account exists, false none, null unknown |
status | enum | completed, pending, unknown, unsupported_country or failed |
confidence / confidence_score | enum / 0–1 | How sure the answer is |
checked_at | timestamp | When the answer was obtained |
cached / age_seconds / billed | boolean / integer / boolean | Cache and billing details |
reason | string or null | Why the answer is not conclusive |
How is it billed?
Per number, for conclusive answers only, at the bulk price. You're not charged for inconclusive results (unknown, unsupported country, timeout, invalid, duplicate). The free POST /v1/jobs/estimate shows the maximum cost first. See pricing.
Numbers your account checked recently can be answered from its cache at no charge. max_age: 0 forces fresh, billed checks.
What are the limits?
MAX runs in bulk jobs only. POST /v1/lookup answers 403 service_disabled ("The check 'max.registered' is available in bulk jobs only (POST /v1/jobs).").
- Up to 50,000 numbers and e-mails per job, 20 checks per request, 100,000 number × check pairs per job.
- Numbers from every country are accepted. Russian numbers in national format (8 9xx …) need
default_country: "RU". - Requests that look like sequential number ranges or generated e-mail lists are rejected.
- A daily number cap applies per account. Follow the job with
GET /v1/jobs/{id}?wait=30or a webhook.
How do I use it responsibly?
Check numbers of customers who gave them to you, for messages they expect. Our acceptable use policy forbids unsolicited messaging, profiling individuals, and checking ranges of numbers to find out who uses a particular app. Russian data protection law has its own requirements for processing personal data of people in Russia, so make sure your processing is lawful. People can object to checks via the opt-out form.
Example request
Test jobs complete at once. +447700900001 answers registered, …002 not registered and …003 unknown. See test mode.
curl https://api.mobilevalidate.com/v1/jobs \
-H "Authorization: Bearer mv_test_publicSandboxn9ZgneuhR1B9CRfKG3fulym" \
-H "Content-Type: application/json" \
-d '{"numbers":["+447700900001","+447700900002","+447700900003"],"checks":["max"]}'// 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.jobs.create({
numbers: ["+447700900001", "+447700900002", "+447700900003"],
checks: ["max"],
});
if (error) console.error(error.code, error.message);
else console.dir(data, { 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/jobs", {
method: "POST",
headers: {
Authorization: "Bearer mv_test_publicSandboxn9ZgneuhR1B9CRfKG3fulym",
"Content-Type": "application/json",
},
body: JSON.stringify({
numbers: ["+447700900001", "+447700900002", "+447700900003"],
checks: ["max"],
}),
});
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.jobs.create(
numbers=["+447700900001", "+447700900002", "+447700900003"],
checks=["max"],
)
print(result)<?php
$ch = curl_init('https://api.mobilevalidate.com/v1/jobs');
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', '+447700900002', '+447700900003'],
'checks' => ['max'],
]),
]);
$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","+447700900002","+447700900003"],"checks":["max"]}`)
req, err := http.NewRequest("POST", "https://api.mobilevalidate.com/v1/jobs", 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/jobs")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer mv_test_publicSandboxn9ZgneuhR1B9CRfKG3fulym"
req["Content-Type"] = "application/json"
req.body = JSON.generate({
"numbers" => ["+447700900001", "+447700900002", "+447700900003"],
"checks" => ["max"]
})
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.
Job (excerpt, test mode):
{
"object": "job",
"id": "job_0VWF4kMMCloqoEvo1IlO",
"status": "completed",
"livemode": false,
"checks": [
"max.registered"
],
"created_at": "2026-09-25T14:25:30.291Z",
"completed_at": "2026-09-25T14:25:30.295Z",
"progress": {
"total": 3,
"checks_total": 3,
"done": 3,
"conclusive": 2,
"non_billable": 3
},
"retention_days": 30
}First row from GET /v1/jobs/{id}/results (test mode):
{
"kind": "phone",
"input": "+44770*****01",
"e164": "+447700900001",
"country": "GB",
"number_status": "valid",
"checks": {
"max.registered": {
"service": "max.registered",
"status": "completed",
"registered": true,
"attributes": null,
"confidence": "high",
"confidence_score": 0.99,
"checked_at": "2026-09-25T14:25:30.295Z",
"cached": false,
"age_seconds": 0,
"billed": false,
"reason": null,
"poll_after_ms": null
}
},
"test": true
}Try it now
Bulk-only service: create a job via POST /v1/jobs, then read GET /v1/jobs/{id}/results. 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/jobs \
-H "Authorization: Bearer mv_test_publicSandboxn9ZgneuhR1B9CRfKG3fulym" \
-H "Content-Type: application/json" \
-d '{"numbers":["+447700900001"],"checks":["max.registered"]}'// 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.jobs.create({
numbers: ["+447700900001"],
checks: ["max.registered"],
});
if (error) console.error(error.code, error.message);
else console.dir(data, { 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/jobs", {
method: "POST",
headers: {
Authorization: "Bearer mv_test_publicSandboxn9ZgneuhR1B9CRfKG3fulym",
"Content-Type": "application/json",
},
body: JSON.stringify({
numbers: ["+447700900001"],
checks: ["max.registered"],
}),
});
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.jobs.create(numbers=["+447700900001"], checks=["max.registered"])
print(result)<?php
$ch = curl_init('https://api.mobilevalidate.com/v1/jobs');
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' => ['max.registered'],
]),
]);
$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":["max.registered"]}`)
req, err := http.NewRequest("POST", "https://api.mobilevalidate.com/v1/jobs", 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/jobs")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer mv_test_publicSandboxn9ZgneuhR1B9CRfKG3fulym"
req["Content-Type"] = "application/json"
req.body = JSON.generate({
"numbers" => ["+447700900001"],
"checks" => ["max.registered"]
})
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 max.registered" → tool: create_lookup_jobThe 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": "max.registered",
"status": "completed",
"registered": true,
"attributes": null,
"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["max.registered"], 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. |
Frequently asked questions
What is MAX?
MAX is a newer Russian messenger that combines chats, calls and access to other services. It is registered with a phone number.
Which numbers is the MAX check useful for?
Mainly Russian numbers, because that is where the app is used. The check accepts numbers from any country, but outside Russia most answers will be not registered.
Why is MAX bulk only?
MAX answers are gathered in batches, so the check runs in POST /v1/jobs. POST /v1/lookup refuses it with service_disabled.
Does the check return names or profile information?
No. Only whether an account is associated with the number.

