Rate Limits & Quotas

The VIN Decoder API implements rate limiting to ensure fair usage and maintain service quality for all users. Rate limits vary by subscription tier.

Two Types of Limits
  1. Rate Limits: Maximum requests per time window (per minute/hour)
  2. Usage Quotas: Total monthly VIN decode allowance

Subscription Tiers

Free Tier

  • Monthly Quota: 100 decodes
  • Rate Limit: 10 req/min
  • Burst Limit: 20 req/hour
  • API Keys: 1
  • Support: Community

Perfect for testing and personal projects

Enterprise

  • Monthly Quota: Custom
  • Rate Limit: Custom
  • Burst Limit: Custom
  • API Keys: Unlimited
  • Support: Priority + SLA

Tailored for high-volume needs

Rate Limit Headers

Every API response includes headers to help you track your rate limit status:

Header Description Example
X-RateLimit-Limit Maximum requests allowed in the current window 60
X-RateLimit-Remaining Requests remaining in the current window 45
X-RateLimit-Reset Unix timestamp when the window resets 1706284800
X-Monthly-Quota-Used VIN decodes used this month 1523
X-Monthly-Quota-Limit Total monthly VIN decode allowance 5000

Example Response Headers

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1706284800
X-Monthly-Quota-Used: 1523
X-Monthly-Quota-Limit: 5000

Handling Rate Limits

When You Hit a Rate Limit

If you exceed your rate limit, you'll receive a 429 Too Many Requests response:

{
  "error": "Rate limit exceeded",
  "detail": "Rate limit of 60 requests per minute exceeded",
  "retry_after": 15
}

The response includes:

  • Retry-After header: Seconds to wait before retrying
  • Error details: Which limit was exceeded

Best Practices

1. Monitor Rate Limit Headers

Check headers on each response to track your usage:

// JavaScript example
fetch(url, options)
  .then(response => {
    const remaining = response.headers.get('X-RateLimit-Remaining');
    const quotaUsed = response.headers.get('X-Monthly-Quota-Used');

    console.log(`Rate limit remaining: ${remaining}`);
    console.log(`Monthly quota used: ${quotaUsed}`);

    if (remaining < 10) {
      console.warn('Approaching rate limit!');
    }

    return response.json();
  });
2. Implement Exponential Backoff

When rate limited, wait progressively longer between retries:

async function requestWithBackoff(url, options, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    const response = await fetch(url, options);

    if (response.status !== 429) {
      return response;
    }

    const retryAfter = response.headers.get('Retry-After') || Math.pow(2, i);
    console.log(`Rate limited. Waiting ${retryAfter} seconds...`);

    await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
  }

  throw new Error('Max retries exceeded');
}
3. Use Caching

Reduce API calls by caching results locally:

  • Cache decoded VINs for repeated lookups
  • Use the GET /decode/{vin} endpoint for cached results (doesn't count against quota)
  • Implement client-side caching with appropriate TTL
4. Batch Wisely

When processing multiple VINs:

  • Add delays between requests (100-200ms recommended)
  • Process in smaller batches during off-peak hours
  • Monitor quota usage before starting large batches

Quota Management

Check Your Usage

Monitor your current usage with the usage endpoint:

GET /api/v1/user/usage

Response:
{
  "subscription_tier": "professional",
  "monthly_limit": 5000,
  "used_this_month": 1523,
  "remaining": 3477,
  "percentage_used": 30.46,
  "reset_date": "2024-02-01T00:00:00Z",
  "daily_usage": {
    "today": 45,
    "yesterday": 62,
    "last_7_days": 312
  }
}

Quota Reset

  • Monthly quotas reset on the 1st of each month at 00:00 UTC
  • Unused quota does not roll over
  • Rate limits reset every minute/hour based on the limit type

Exceeding Monthly Quota

When you exceed your monthly quota:

  1. You'll receive a 429 error with quota details
  2. Consider upgrading your subscription
  3. Or wait until the next month for quota reset
Important Notes
  • Rate limits apply per API key, not per account
  • Cached lookups (GET /decode/{vin}) don't count against quota
  • Invalid VIN requests still count against rate limits (but not quota)
  • Webhooks and batch processing may have different limits

Need Higher Limits?

If you need higher rate limits or quotas: