Authentication
How MobileValidate API keys work: test, live and agent keys, scopes, IP allowlists for IPv4 and IPv6, and what a 401 means.
Last updated
View as MarkdownEvery request authenticates with an API key sent as a bearer token: Authorization: Bearer <key>. There are three kinds of key: test, live and agent. The key's prefix tells you which kind it is. Keys carry scopes and can be locked to IP addresses. Any key problem returns the same 401 unauthorized.
What kinds of key are there?
| Prefix | Kind | What it does |
|---|---|---|
mv_test_ | Test | Answers from fixed test data. Never reaches a real network, never billed. Real numbers get deterministic fake answers. |
mv_test_publicSandbox… | Public sandbox | A test key published in these docs so every example runs as pasted. Only the documented test numbers and addresses (403 sandbox_magic_only otherwise), per-IP limits, jobs up to 10 rows, no webhooks. |
mv_live_ | Live | Real checks, billed per conclusive answer. Test numbers and the test e-mail domain are refused (test_number_only). |
mv_agent_ | Agent | For AI agents and the MCP server. Only the scopes it was given, plus a daily spend cap. |
A key is its prefix, 30 random base62 characters and a 6-character checksum. The checksum lets secret scanners and our API spot a mistyped or truncated key. We store only a keyed hash of each key, so a key is shown once, when it is created. If you lose a key, ask for a new one and revoke the old one.
Keep keys on your servers. Don't put them in front-end code, mobile apps, URLs or logs. The SDKs, the CLI and the MCP server read MOBILEVALIDATE_API_KEY from the environment and never print it. It is the only variable name we use.
What are scopes?
Scopes limit what a key can do. A request outside a key's scopes gets 403 insufficient_scope.
| Scope | Allows |
|---|---|
lookup:write | POST /v1/lookup, GET /v1/lookups/{id} |
jobs:write | POST /v1/jobs/estimate, POST /v1/jobs, DELETE /v1/jobs/{id} |
jobs:read | Read your own jobs, their results and downloads |
jobs:read_all | Read every job in the account (by default a key sees only the jobs it created). Any lookup:write key can read the account's lookups. |
account:read | GET /v1/account, /v1/limits, /v1/usage |
webhooks:manage | Create, change, test and delete webhook endpoints |
Test and live keys without an explicit list get every scope except webhooks:manage, which has to be granted on purpose. The public sandbox key never has webhooks:manage or jobs:read_all. Agent keys have exactly the scopes they were issued with. GET /v1/services and GET /v1/health work without a key; with a key, /v1/services shows what your account can use, with your prices. An unknown path returns 404 not_found before the key is checked.
How do IP allowlists work?
A key can be restricted to a list of IP addresses or CIDR ranges. Requests from anywhere else are refused with the same 401 unauthorized as a bad key. Some live keys must have an allowlist, depending on your account.
- Entries can be single addresses (
203.0.113.10) or ranges (203.0.113.0/24,2001:db8:1234::/48). - IPv4 and IPv6 are both supported. An IPv4-mapped IPv6 address (
::ffff:203.0.113.10) is matched as its IPv4 address. - IPv6 note: servers and networks with IPv6 often rotate their source address (privacy extensions, cloud NAT, container networking). A dual-stack client may also switch from IPv4 to IPv6 without warning. Allow your IPv6 prefix, usually the
/64of the host or the/56or/48assigned to your network, rather than a single address. You can also force your client to use IPv4.
What happens when authentication fails?
A missing, malformed, unknown, revoked or expired key, or a key used from an address outside its allowlist, returns:
{"error": {"code": "unauthorized", "message": "…", "status": 401, "retryable": false, "param": null,
"doc_url": "https://mobilevalidate.com/docs/errors#unauthorized", "request_id": "req_…"}}The answer is the same in every case on purpose, so nobody can probe which keys exist. Retrying won't help. Check the prefix, check for a trailing space or line break, and check your server's outgoing IP address. Include the request_id when you contact support.
Frequently asked questions
Why does a wrong IP address give the same error as a wrong key?
A missing, unknown, revoked, expired or wrong-IP key always returns the same 401 unauthorized, so the response never tells an attacker which part was wrong. Your account team can see the exact cause in the audit log.
My allowlisted server suddenly gets 401. What changed?
Often the server started connecting over IPv6, or its IPv6 address rotated. Add your IPv6 prefix (for example a /64) as well as your IPv4 address.
Can I put the key in a query string?
No. Keys go only in the Authorization header. Never embed a key in browser or mobile app code; call the API from your backend.

