> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pipecorn.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Rate Limiting

> Understanding API rate limits and best practices

Our API implements rate limiting to ensure fair usage and maintain service stability for all users. Understanding these limits will help you optimize your API usage and avoid disruptions.

## Plan Rate Limits

Every v2 endpoint has a per-minute request limit that depends on your plan:

| Plan | Requests per minute |
| - | - |
| Free | 1 |
| Basic | 2 |
| Starter, Premium, Build | 10 |
| Advanced, Professional, Growth, Boost | 100 |
| Scale, Enterprise, Agency, Team | 1000 |

Plans not listed fall back to the Free limit.

Limits are counted **per user**, not per API key: every key belonging to the same user shares the same counters. Each endpoint group has its own counter (endpoints served together, such as `POST /accounts/search` and `POST /accounts/search/preview`, share one).

## Exempt Endpoints

Endpoints that spend enrichment credits are exempt from the plan limit: the credit balance is their own throttle.

* `POST /contacts/single_enrich` (async and synchronous)
* `POST /contacts/bulk_enrich`
* `POST /contacts/reverse_lookup`
* `POST /leads/single_enrich`
* `POST /accounts/single_enrich`
* `POST /accounts/company_stack`
* `POST /accounts/company_hiring` (keeps its own per-second limit, see below)
* `POST /intents/accounts/hiring`
* `POST /intents/accounts/stack`
* `POST /whatsapp_validations`

Status and account lookups are exempt too, so you can poll them while an async job runs:

* `GET /contacts/{id}`
* `GET /contacts/{id}/single_enrich`
* `GET /searches/{id}`
* `GET /lists/{id}`
* `GET /account`
* `GET /credits`

`POST /leads/search` is exempt with `live: true` (the default); with `live: false` it follows the plan limit.

## Endpoint-Specific Limits

A few endpoints add a stricter limit on top of the plan limit, also counted per user:

| Endpoint | Limit |
| - | - |
| `POST /accounts/headcount` | 20 requests per second |
| `POST /accounts/count_profiles` | 20 requests per second |
| `POST /accounts` | 20 requests per minute |
| `POST /leads` | 1 request per second |
| `POST /leads/advanced_search` | 1 request per second |
| `POST /leads/advanced_search/preview` | 1 request per second (5 per second with `live: false`) |
| `POST /accounts/company_hiring` | 5 requests per second |

## Understanding Rate Windows

Each counter opens a window on its first request and resets when the window ends. For example:

* On a plan with 10 requests per minute, if your first request to `POST /accounts/search` lands at 10:00:30, you can make 9 more until 10:01:30
* If you make a request to `POST /leads` at 10:00:00, you'll need to wait 1 second before making another request

## Rate Limit Responses

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

```json theme={null}
{
  "error": "Rate limit exceeded. Please wait before retrying."
}
```

Live endpoints that call LinkedIn can also return `429` when LinkedIn itself rate limits your account:

```json theme={null}
{
  "error": "Rate limited by LinkedIn. Please wait a few hours before retrying."
}
```

## Best Practices

1. **Implement Endpoint-Specific Retry Logic**

   * Add exponential backoff with appropriate intervals for each endpoint
   * Use short retry intervals (1-5 seconds) for endpoints with a per-second limit
   * Wait for the window to reset (up to 60 seconds) when you hit your plan limit
   * Back off for hours, not seconds, when LinkedIn rate limits you
   * Include jitter to prevent thundering herd problems

2. **Optimize Request Patterns**

   * Use bulk endpoints when available (e.g., `/contacts/bulk_enrich`)
   * Space out search requests according to their specific time windows
   * Queue requests that would exceed rate limits

3. **Handle Rate Limits Gracefully**
   * Implement proper error handling for 429 responses
   * Use different queues for different endpoint types
   * Consider using a rate limiting library in your client

## Example Retry Implementation

Here's a simple example of how to implement retry logic with endpoint-specific timing:

```ruby theme={null}
def make_request_with_retry(endpoint, max_retries = 3)
  retries = 0
  # Define wait times based on endpoint type
  wait_time = case endpoint
              when %r{/leads(/advanced_search(/preview)?)?$}
                1  # 1 request per second
              when %r{/accounts/(headcount|count_profiles|company_hiring)$}
                1  # per-second limits
              else
                60 # wait for the per-minute window to reset
              end

  begin
    response = api_client.call(endpoint)
    return response
  rescue RateLimitExceeded => e
    raise if retries >= max_retries

    retries += 1
    # Add jitter to prevent thundering herd
    sleep_time = wait_time + rand(0.1..0.5)
    sleep(sleep_time)
    retry
  end
end
```

## Additional Considerations

* Rate limits are applied per user, not per API key
* Each endpoint group's rate limit is tracked separately
* Credit-spending and status-polling endpoints are exempt from the plan limit
* Consider implementing separate queues for different endpoint types
* Monitor your usage patterns and adjust your implementation accordingly

For questions about rate limits or to request limit increases, please contact our support team.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.