Rate limits
How Verifycate throttles API requests and how to handle HTTP 429
To keep the API reliable for every workspace, Verifycate limits how quickly clients may send requests. Limits use fixed time windows and apply per client identity (IP, API key, or IP plus email for OTP).
Rate-limited requests return HTTP 429 with error code rate_limited. Integrations should treat 429 as temporary and retry after waiting.
Response
When a limit is exceeded:
| Signal | Meaning |
|---|---|
| Status | 429 Too Many Requests |
Body code | rate_limited |
Header Retry-After | Integer seconds to wait before retrying |
Example body (application/problem+json):
{
"title": "Too Many Requests",
"status": 429,
"detail": "rate limit exceeded; retry later",
"code": "rate_limited"
}Example headers:
HTTP/1.1 429 Too Many Requests
Retry-After: 42
Content-Type: application/problem+jsonHow to handle limits
- Detect
status === 429(and optionallycode === "rate_limited"). - Read
Retry-Afterand wait at least that many seconds before retrying the same request. - Prefer backing off or queueing outbound calls so you stay under the average rate, instead of hammering the API until you hit 429.
A common pattern is a request queue that only sends the next call when the previous response was not 429 (or after the Retry-After delay).
See also Errors for the shared problem+json shape.
Default limits
These are the default ceilings. Values may change as we balance demand and reliability; always rely on Retry-After rather than hard-coding sleep times.
| Bucket | Applies to | Limit |
|---|---|---|
| API key | Authenticated requests using a workspace API key (Authorization: Bearer vc_…) | 120 requests / minute per key |
| Default | Session/JWT and other authenticated app traffic | 300 requests / minute per IP |
| Public | Public certificate view/verify, request forms, corrections, public workspace/media | 60 requests / minute per IP |
| OTP request | POST /api/v1/auth/otp/request | 5 requests / 15 minutes per IP + email |
| OTP verify | POST /api/v1/auth/otp/verify | 10 requests / 15 minutes per IP + email |
GET /api/v1/health is not rate limited.
For API integrations, the API key row is the one that matters day to day. Stay around 2 requests per second sustained if you issue or send in bulk; short bursts are fine until the per-minute window fills.
Tips for bulk work
- Prefer batch endpoints (for example Import issues and Send pending certificates) over many tiny calls.
- When paging with Pagination, space list requests or reuse a single client with backoff.
- Do not share one API key across unrelated high-volume jobs if you need independent budgets; create separate keys per integration.