Rate Limits
VerifNow enforces quotas per billing period and concurrent request limits to ensure fair usage and API stability. This guide explains the limits for each plan and how to handle them.
Plans & limits
| Plan | Validations per billing period | Concurrent requests | Max active API keys | Overage behavior |
|---|---|---|---|---|
| FREE | 250 | 3 | 1 | Blocked |
| STARTER | 10,000 | 5 | 2 | Billed per unit |
| GROWTH | 50,000 | 10 | 5 | Billed per unit |
| PRO | 150,000 | 25 | 20 | Billed per unit |
How quotas work
- FREE plan: once you reach 250 validations in your billing period, subsequent requests are blocked with a
429response. The FREE plan runs the sameSTANDARDchecks as STARTER — the two differ in volume, not in depth. - Paid plans (STARTER, GROWTH, PRO): requests above the included quota are not blocked. Instead, they are billed per unit at the end of the billing period.
- Quota reset: quotas reset at the start of each billing period. The billing period is tied to your subscription start date — for example, if your subscription started on the 4th, quotas reset every 4th of the month for a monthly subscription.
Limits are per account, not per key: every API key on your account draws on the same quota and the same concurrency allowance.
Concurrent request limits
Each plan has a maximum number of simultaneous (concurrent) requests that can be in-flight at the same time. If you exceed this limit, the API returns a 429 Too Many Requests response — regardless of your plan.
| Plan | Max concurrent requests |
|---|---|
| FREE | 3 |
| STARTER | 5 |
| GROWTH | 10 |
| PRO | 25 |
Unlike quota limits (which only block FREE plans), concurrent request limits apply to all plans. If you send more simultaneous requests than your plan allows, the extra requests will be rejected with a 429 status.
For service protection, non-PRO plans (FREE, STARTER, GROWTH) are also subject to shared per-server concurrency controls. This means a request from a non-PRO plan can occasionally receive a 429 even if it is the only request currently in flight for that API key, or even if you are still within your plan’s documented concurrent request limit.
A 429 on a non-PRO plan does not always mean you exhausted your quota or exceeded your own per-plan concurrency. It can also be a temporary server-side protection to preserve capacity for higher-service tiers. In that case, retry the request after a short backoff.
API key limits
Each plan has a maximum number of active API keys you can have at the same time:
| Plan | Max active API keys |
|---|---|
| FREE | 1 |
| STARTER | 2 |
| GROWTH | 5 |
| PRO | 20 |
If you need more API keys, consider upgrading your plan at app.verifnow.io .
Rate limit headers
Every successful validation carries your quota state:
HTTP/2 200
X-RateLimit-Limit: 10000
X-RateLimit-Remaining: 9812
X-RateLimit-Reset: 1790985600
X-Request-Id: 7d0e…| Header | Description |
|---|---|
X-RateLimit-Limit | Validations included in the current billing period |
X-RateLimit-Remaining | Validations left before the quota is reached — 0 once you are past it |
X-RateLimit-Reset | Unix timestamp (seconds) when the current period ends |
X-Quota-Overage | true once a paid plan is past its included quota and into per-unit billing |
The Node.js SDK reads these for you: result.quota in @verifnow/sdk carries limit, remaining, resetAt
(a Date) and overage.
When you get a 429
A 429 means one of two very different things. Tell them apart before retrying — one clears in a
second, the other not before your period resets.
Too many requests in flight (all plans)
You sent more simultaneous requests than your plan allows. It clears as soon as one of your requests finishes.
HTTP/2 429
Retry-After: 1
{"status": 429, "message": "Too many requests in flight for this account. Retry in a moment."}Retry after Retry-After seconds — the Node.js SDK does this automatically. If it keeps happening, you are
sending more in parallel than your plan allows: lower your concurrency, or move up a plan.
Monthly quota spent (FREE plan)
Only the FREE plan is blocked at its quota. The edge rejects the request before it reaches the API, and tells you where you stand:
HTTP/2 429
{"error": "Monthly quota exceeded", "limit": 250, "usage": 250, "periodStart": "2026-09-04"}It will not clear before the period resets, so do not retry: upgrade, or wait for the next
period. In the rare case where the API enforces the quota itself, the response is
{"status": 429, "message": "Monthly quota exceeded. Upgrade your plan or wait for the next period."}
with a Retry-After counting down to the reset — days, not seconds.
Telling them apart in code: a concurrency 429 has Retry-After: 1. A quota 429 has either no
Retry-After or a very long one. Retry the first, surface the second.
Overage on paid plans
On paid plans (STARTER, GROWTH, PRO), requests above the included quota are allowed and billed at
the per-unit rate at the end of the billing period. They carry X-Quota-Overage: true:
HTTP/2 200
X-RateLimit-Limit: 10000
X-RateLimit-Remaining: 0
X-Quota-Overage: trueWatching your quota in code
With the SDK, every result carries the quota state it was answered with:
import { VerifNow, VerifNowRateLimitError } from '@verifnow/sdk'
const client = new VerifNow({ apiKey: process.env.VERIFNOW_API_KEY! })
export async function validateAndWatchQuota(email: string) {
try {
const result = await client.validateEmail(email)
const quota = result.quota
if (quota?.remaining !== undefined && quota.remaining < 50 && !quota.overage) {
console.warn(`Low quota: ${quota.remaining} left, resets ${quota.resetAt?.toISOString()}`)
}
return result
} catch (error) {
if (error instanceof VerifNowRateLimitError) {
// The SDK has already retried a concurrency 429. What reaches you here is, in practice,
// a spent FREE quota: surface it rather than sleeping on it.
console.error('VerifNow quota exhausted', { retryAfterSeconds: error.retryAfterSeconds })
}
throw error
}
}Without the SDK, read the same headers from the response — and branch on Retry-After for a 429,
as described above.
Best practices
- Monitor
X-RateLimit-Remainingin every response — don’t wait for a 429 to find out - Retry a
429only whenRetry-Afteris short — that is a concurrency limit. A spent quota will not clear by waiting. See Error Handling - Cache results — if you’ve already validated an email recently, reuse the result
- Upgrade your plan if you consistently exceed your quota — visit app.verifnow.io
- Track your usage in the dashboard under Usage & Billing
Bulk (batch) validation is not yet available. For now, validate one item at a time via the API.
Quota reset schedule
Quotas are reset at the start of each billing period, aligned with your subscription start date:
- Monthly subscription started on the 4th: quota resets on the 4th of each month
- Monthly subscription started on the 15th: quota resets on the 15th of each month
This is different from a calendar-month reset. Check the X-RateLimit-Reset header or your dashboard for the exact reset date.