VANITYPASS
B2B API

Rate Limiting

API rate limits, identities, and backoff behavior.

Rate Limiting

VanityPass applies application-layer rate limits to every /v1 request. The global limit uses the first verified identity available: JWT user, tenant app/API key, then client IP. Invalid credentials do not create a new bucket; those requests fall back to the trusted client IP.

Tenant-configured quotas may apply independently. When more than one policy applies, a request must pass every policy.

Default security limits

SurfaceIdentityDefault
All /v1 endpointsVerified user, then verified app, then client IP100 requests / 10 seconds
Authentication endpointsClient IP30 requests / minute
Authentication targetHMAC-protected email/account plus app5 requests / 5 minutes; repeated lockout: 10 minutes
User searchClient IP plus verified user/app60 requests / minute per IP; 30 requests / minute per user
Experiences catalogClient IP20 requests / 10 seconds
WebhooksClient IP10 requests / second and 120 requests / minute

Client IP limits apply regardless of authentication. This prevents account, token, app-header, or email rotation from bypassing the protection.

When a limit is exceeded

A rejected request returns 429 Too Many Requests and these headers:

  • Retry-After: positive number of seconds before retrying.
  • X-RateLimit-Limit: maximum requests in the window that was exceeded.
  • X-RateLimit-Remaining: 0.
  • X-RateLimit-Reset: Unix epoch second when that window resets.
HTTP/1.1 429 Too Many Requests
Retry-After: 7
X-RateLimit-Limit: 20
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1785678901
{
  "status": "fail",
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Too many requests. Retry after the indicated delay."
  }
}

Backoff strategy

Honor Retry-After as the minimum delay. Add a small random jitter before retrying so concurrent clients do not resume at the same instant. If Retry-After is unavailable, use capped exponential backoff. Stop retrying after a bounded number of attempts and surface the failure to the caller.

Do not change credentials or spoof forwarding headers to obtain another bucket. Forwarded client addresses are accepted only from the configured trusted ingress chain.