> For the complete documentation index, see [llms.txt](https://docs.partssource.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.partssource.com/api/core-concepts/rate-limiting.md).

# Rate Limiting

Understanding API rate limits and how to handle them

The PartsSource APIs implement rate limiting to ensure fair usage and system stability. Understanding these limits helps you design robust integrations.

***

## Rate Limits

| Tier       | Requests/Second | Burst Limit    |
| ---------- | --------------- | -------------- |
| Standard   | 1,000 RPS       | 2,000 requests |
| Enterprise | Custom          | Custom         |

{% hint style="info" %}
Rate limits are applied per API client (identified by your `client_id`). Contact your account manager for enterprise tier access.
{% endhint %}

***

## Rate Limit Headers

Every API response includes rate limit information in headers:

```http
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 999
X-RateLimit-Reset: 1634825400
```

| Header                  | Description                          |
| ----------------------- | ------------------------------------ |
| `X-RateLimit-Limit`     | Maximum requests allowed per second  |
| `X-RateLimit-Remaining` | Requests remaining in current window |
| `X-RateLimit-Reset`     | Unix timestamp when the limit resets |

***

## Rate Limit Exceeded Response

When you exceed the rate limit, you'll receive a `429 Too Many Requests` response:

```http
HTTP/1.1 429 Too Many Requests
Retry-After: 1
Content-Type: application/json

{
  "type": "https://tools.ietf.org/html/rfc6585#section-4",
  "title": "Too Many Requests",
  "status": 429,
  "detail": "Rate limit exceeded. Please retry after 1 second.",
  "correlationId": "0HN7QJKV3QJ8K:00000001"
}
```

The `Retry-After` header indicates how many seconds to wait before retrying.

***

## Handling Rate Limits

### Basic Retry Strategy

```csharp
public async Task<T> ExecuteWithRateLimitRetry<T>(Func<Task<HttpResponseMessage>> request)
{
    var response = await request();

    if (response.StatusCode == HttpStatusCode.TooManyRequests)
    {
        // Get retry delay from header, default to 1 second
        var retryAfter = response.Headers.RetryAfter?.Delta
            ?? TimeSpan.FromSeconds(1);

        await Task.Delay(retryAfter);
        response = await request();
    }

    response.EnsureSuccessStatusCode();
    return await response.Content.ReadFromJsonAsync<T>();
}
```

### Exponential Backoff

For production systems, implement exponential backoff:

```csharp
public async Task<T> ExecuteWithExponentialBackoff<T>(
    Func<Task<HttpResponseMessage>> request,
    int maxRetries = 5)
{
    for (int attempt = 0; attempt < maxRetries; attempt++)
    {
        var response = await request();

        if (response.IsSuccessStatusCode)
        {
            return await response.Content.ReadFromJsonAsync<T>();
        }

        if (response.StatusCode != HttpStatusCode.TooManyRequests)
        {
            response.EnsureSuccessStatusCode(); // Throw for non-429 errors
        }

        // Exponential backoff: 1s, 2s, 4s, 8s, 16s
        var delay = TimeSpan.FromSeconds(Math.Pow(2, attempt));

        // Respect Retry-After header if provided
        if (response.Headers.RetryAfter?.Delta is TimeSpan retryAfter)
        {
            delay = retryAfter > delay ? retryAfter : delay;
        }

        await Task.Delay(delay);
    }

    throw new RateLimitExceededException("Max retries exceeded");
}
```

### TypeScript Example

```typescript
async function fetchWithRateLimitRetry<T>(
  url: string,
  options: RequestInit,
  maxRetries = 5
): Promise<T> {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    const response = await fetch(url, options);

    if (response.ok) {
      const data = await response.json();
      return data.data as T;
    }

    if (response.status !== 429) {
      throw new Error(`HTTP ${response.status}: ${response.statusText}`);
    }

    // Get retry delay
    const retryAfter = response.headers.get('Retry-After');
    const baseDelay = Math.pow(2, attempt) * 1000; // Exponential backoff
    const delay = retryAfter
      ? Math.max(parseInt(retryAfter) * 1000, baseDelay)
      : baseDelay;

    console.log(`Rate limited. Retrying in ${delay}ms...`);
    await new Promise(resolve => setTimeout(resolve, delay));
  }

  throw new Error('Max retries exceeded due to rate limiting');
}
```

### Python Example

```python
import time
import requests

def fetch_with_rate_limit_retry(url, headers, max_retries=5):
    for attempt in range(max_retries):
        response = requests.get(url, headers=headers)

        if response.ok:
            return response.json()['data']

        if response.status_code != 429:
            response.raise_for_status()

        # Calculate delay with exponential backoff
        base_delay = 2 ** attempt
        retry_after = int(response.headers.get('Retry-After', 0))
        delay = max(base_delay, retry_after)

        print(f"Rate limited. Retrying in {delay}s...")
        time.sleep(delay)

    raise Exception("Max retries exceeded due to rate limiting")
```

***

## Best Practices

### 1. Monitor Rate Limit Headers

Track your remaining quota proactively:

```csharp
public void LogRateLimitStatus(HttpResponseMessage response)
{
    if (response.Headers.TryGetValues("X-RateLimit-Remaining", out var remaining))
    {
        var remainingCount = int.Parse(remaining.First());

        if (remainingCount < 100)
        {
            _logger.LogWarning(
                "Rate limit warning: {Remaining} requests remaining",
                remainingCount);
        }
    }
}
```

### 2. Implement Request Queuing

For high-volume operations, queue requests to stay under limits:

```csharp
public class RateLimitedHttpClient
{
    private readonly SemaphoreSlim _semaphore;
    private readonly HttpClient _httpClient;
    private readonly int _requestsPerSecond;

    public RateLimitedHttpClient(HttpClient httpClient, int requestsPerSecond = 100)
    {
        _httpClient = httpClient;
        _requestsPerSecond = requestsPerSecond;
        _semaphore = new SemaphoreSlim(requestsPerSecond, requestsPerSecond);
    }

    public async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request)
    {
        await _semaphore.WaitAsync();

        try
        {
            return await _httpClient.SendAsync(request);
        }
        finally
        {
            // Release after delay to maintain rate
            _ = Task.Delay(1000).ContinueWith(_ => _semaphore.Release());
        }
    }
}
```

### 3. Cache Responses

Reduce API calls by caching frequently-accessed data:

```csharp
public class CachedApiClient
{
    private readonly IMemoryCache _cache;
    private readonly HttpClient _httpClient;

    public async Task<Customer> GetCustomer(long customerId)
    {
        var cacheKey = $"customer:{customerId}";

        if (_cache.TryGetValue(cacheKey, out Customer cached))
        {
            return cached;
        }

        var response = await _httpClient.GetAsync($"/customers/lookup?customerId={customerId}");
        var customer = await response.Content.ReadFromJsonAsync<Customer>();

        _cache.Set(cacheKey, customer, TimeSpan.FromMinutes(5));
        return customer;
    }
}
```

### 4. Use Pagination Efficiently

Fetch only the data you need:

```json
{
  "filters": {"status": "active"},
  "pagination": {
    "limit": 100,
    "offset": 0
  }
}
```

* Use reasonable page sizes (50-100 records)
* Filter results server-side when possible
* Don't fetch all pages if you only need the first few

### 5. Batch Operations

Combine multiple operations where possible to reduce total requests.

***

## Troubleshooting

### Consistently hitting rate limits?

1. **Audit your integration** - Are you making unnecessary calls?
2. **Implement caching** - Cache responses that don't change frequently
3. **Use webhooks** - If available, prefer push over polling
4. **Contact support** - Request enterprise tier for higher limits

### Rate limit headers missing?

The headers are only present on authenticated requests. Verify you're including a valid `Authorization` header.

### Getting 429s even with low volume?

1. Check if other applications share your credentials
2. Verify you're not making parallel requests unintentionally
3. Check for retry loops that could amplify traffic


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.partssource.com/api/core-concepts/rate-limiting.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
