# Rate limits and anti-abuse rules

> MobileValidate API limits: 10 requests/s per key, daily caps, spend caps, request sizes, and the anti-enumeration rules that block number and e-mail scans.

Canonical: https://mobilevalidate.com/docs/rate-limits-and-abuse · Last updated: 2026-09-25

Machine-readable: [Limits in key facts (JSON)](https://mobilevalidate.com/facts.json)

Every key is limited to 10 requests per second, with bursts of up to 20. Every account has a daily cap on the numbers and e-mails it can check. On top of that, requests that look like sequential number ranges or generated e-mail lists are rejected. These limits keep the service fast for everyone and stop the API from being used to find out who owns a number or address.

## How does the request rate limit work?

Each key has a token bucket: 10 requests per second on average, with a burst of 20. When you go over, you get `429 rate_limited` with a `Retry-After` header. Every authenticated response carries the current state in IETF RateLimit headers:

```text
RateLimit-Policy: "default";q=20;w=2
RateLimit: "default";r=19;t=1
```

`q` is the bucket size, `w` the window in seconds, `r` the requests remaining, and `t` the seconds until the bucket is full again. The most effective way to stay under the limit is to batch: one lookup takes up to 100 identifiers, and one job takes up to 50,000. Test keys are limited in the same way. The public sandbox key is shared by everyone, so it is limited per IP address instead: 30 requests per minute and 1,000 per UTC day (policies `sandbox-minute` and `sandbox-day` in the same headers), and jobs of at most 10 rows.

## What are the daily and spend caps?

| Limit | Where to see it | Resets |
|---|---|---|
| Daily identifiers (valid numbers + valid e-mails checked) | `GET /v1/limits` → `daily_numbers.cap`, `used`, `remaining` | 00:00 UTC |
| Key daily spend (agent keys) | `GET /v1/limits` → `key_daily_spend` | 00:00 UTC |
| Key daily spend cap reached | error `spend_cap_reached` | 00:00 UTC |

```json
{"object": "limits", "rate_limit": {"requests_per_second": 10, "burst": 20},
 "lookup": {"max_numbers": 100, "max_wait_seconds": 30, "realtime_enabled": true},
 "jobs": {"max_numbers": 50000},
 "daily_numbers": {"cap": 50000, "used": 19, "remaining": 49981},
 "key_daily_spend": null, "resets_at": "2026-09-26T00:00:00.000Z"}
```

(Real test-mode output. Your values depend on your account.) The daily cap counts identifiers, not checks. A number checked against five services counts once. Hitting a cap returns `429 daily_cap_reached`. `max_cost` on each request gives you your own ceiling as well.

## What are the request size limits?

| Limit | Value |
|---|---|
| Identifiers per lookup | 100 numbers + e-mails |
| Identifiers per job | 50,000 numbers + e-mails |
| Checks per request | 20 |
| Identifiers × applicable checks | 2,000 per lookup, 100,000 per job |
| Request body | 1 MB; 4 MB for `POST /v1/jobs` and `/v1/jobs/estimate` |
| Long-poll `wait` | up to 30 s |
| Webhook endpoints | 20 per account |

All size limits, `max_cost`, caps and your balance are checked before any identifier is stored, so a refused request leaves no data behind.

## What counts as enumeration?

Requests that look like sequential number ranges or generated e-mail lists are rejected with `403 suspected_enumeration`:

- **Number ranges:** 20 or more numerically consecutive numbers in one request, for example `+447700900100` to `+447700900119`.
- **Generated addresses in a request:** 20 or more distinct addresses on one domain whose local parts differ only by digits or separators (`john1@`, `john.2@`, `john_3@`…). `gmail.com` and `googlemail.com` count as one domain.
- **Generated addresses across a day (live keys):** 50 or more distinct addresses of one such pattern from the same account in one UTC day, however they are split across requests.

The rules exist because checking made-up ranges is how people try to build lists of platform users. Our [acceptable use policy](/legal/acceptable-use) forbids that. Checks are for identifiers you already hold, such as customers, sign-ups and leads, and for purposes like fraud prevention and deliverability.

## What else protects people whose data is checked?

- **Suppression list:** people can object through the [opt-out form](/opt-out). Suppressed numbers and addresses are returned as `suppressed`, never checked and never billed.
- **No personal data in answers:** checks return yes/no/unknown or network and reputation attributes, never names, photos, profiles or locations.
- **Masking:** stored results and downloads show masked identifiers (`+44770*****01`, `re•••@…`), and logs never contain full numbers.
- **Kill switch:** we can switch off a service for everyone within minutes if it is being abused.

Repeated abuse can lead to suspension of the account under the acceptable use policy.

## Frequently asked questions

### Can I get higher limits?

Yes. Daily caps and throughput are set per account and can be raised for established use cases. GET /v1/limits always shows your current values.

### Why was my list of customer numbers rejected as enumeration?

20 or more numerically consecutive numbers in one request trigger the rule, which can happen with test data or sorted internal ranges. Real customer lists rarely contain long consecutive runs; shuffle genuine data or contact us if your use case needs an exception.
