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

> ## Agent Instructions
> AhaSend stores all message data in the EU. See /facts.
> The API base URL is https://api.ahasend.com. Send the API key in the Authorization: Bearer header. See /api-reference/authentication.
> Use send.ahasend.com for SMTP. Ports 25, 587 and 2525 use STARTTLS. Port 465 is not supported. See /smtp.
> For send-only integrations, create an API Key v2 under Credentials → Add and scope it to messages:send:{your-domain}. See /send-api/credentials and /api-reference/scopes.

# API Rate Limits and 429 Handling

> AhaSend API v2 allows 100 requests/second per account (burst 200); statistics endpoints allow 1/second. Learn what a 429 response looks like and how to retry.

AhaSend API rate limits apply per account; this reference lists request limits, explains HTTP 429, and shows how to retry.

## Overview

AhaSend API implements rate limiting to ensure fair usage and maintain optimal performance for all users. Rate limits are applied per account and vary depending on the endpoint category.

> [!WARNING]
>
> Rate limits are enforced per account, not per API key. All API keys belonging to the same account share the same rate limit quotas.

## Rate Limit Tiers

### Standard API Endpoints

Most API endpoints are subject to the following rate limits:

> [card] Request Rate
>
> **100 requests per second**
>
> Maximum sustained request rate

> [card] Burst Capacity
>
> **200 requests**
>
> Short-term burst allowance

**Affected Endpoints:** all other v2 endpoints, including `/v2/ping`, account members, sub-accounts and sub-account usage.

* `/v2/accounts/*` - Account management
* `/v2/accounts/{account_id}/api-keys/*` - API key management
* `/v2/accounts/{account_id}/domains/*` - Domain management
* `/v2/accounts/{account_id}/messages/*` - Message operations
* `/v2/accounts/{account_id}/suppressions/*` - Suppression management
* `/v2/accounts/{account_id}/routes/*` - Route management
* `/v2/accounts/{account_id}/webhooks/*` - Webhook management
* `/v2/accounts/{account_id}/smtp-credentials/*` - SMTP credential management

### Statistics, Stream and Trigger Endpoints

Statistics, webhook and route stream, and test-trigger endpoints have a separate limit of 1 request per second:

> [card] Request Rate
>
> **1 request per second**
>
> Sustained request rate

> [card] Burst Capacity
>
> **1 request**
>
> No burst allowance

**Affected Endpoints:**

* `/v2/accounts/{account_id}/statistics/transactional/deliverability`
* `/v2/accounts/{account_id}/statistics/transactional/bounce`
* `/v2/accounts/{account_id}/statistics/transactional/delivery-time`

## Rate Limit Exceeded Response

When you exceed the rate limit, the API returns a `429 Too Many Requests` status code:

```json Rate Limit Error Response theme={null}
{
  "message": "Too many requests, rate limited."
}
```

> [!NOTE]
>
> Requests share the account limit. Spread requests over time; a new second does not reset a fixed request counter. A rate-limit `429` carries a `Retry-After` header with the number of seconds to wait before you retry. Do not depend on `X-RateLimit-*` headers.

[Test Campaign](https://ahasend.com/docs/api-reference/campaigns/test-campaign.md) also answers `429` when your account reaches its daily test limit. Backoff does not clear that `429`. See [Test Campaign](https://ahasend.com/docs/api-reference/campaigns/test-campaign.md) for the rules of the limit.

## Best Practices

### 1. Implement Exponential Backoff

When you receive a 429 response, implement exponential backoff with jitter:

```javascript JavaScript Example theme={null}
async function makeRequestWithRetry(url, options, maxRetries = 3) {
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    try {
      const response = await fetch(url, options);

      if (response.status === 429) {
        if (attempt === maxRetries) {
          throw new Error('Rate limit exceeded after max retries');
        }

        // Exponential backoff with jitter
        const delay = Math.pow(2, attempt) * 1000 + Math.random() * 1000;
        await new Promise(resolve => setTimeout(resolve, delay));
        continue;
      }

      return response;
    } catch (error) {
      if (attempt === maxRetries) throw error;
    }
  }
}
```

```python Python Example theme={null}
import time
import random
import requests

def make_request_with_retry(url, headers, max_retries=3):
    for attempt in range(max_retries + 1):
        response = requests.get(url, headers=headers)

        if response.status_code == 429:
            if attempt == max_retries:
                raise Exception("Rate limit exceeded after max retries")

            # Exponential backoff with jitter
            delay = (2 ** attempt) + random.random()
            time.sleep(delay)
            continue

        return response
```

### 2. Batch Operations When Possible

For operations that support batching, group multiple items into single requests:

> [!TIP]
>
> Instead of sending 100 individual message requests, consider using bulk operations or queuing messages to reduce API calls.

### 3. Cache Frequently Accessed Data

Cache static or slowly-changing data like account information and domain lists to reduce unnecessary API calls.

### 4. Use Webhooks for Real-time Updates

Instead of polling endpoints repeatedly, configure webhooks to receive real-time notifications about message status changes and other events.

## Statistics API Considerations

> [!WARNING]
>
> Statistics endpoints have very restrictive rate limits (1 request per second). Plan your analytics queries carefully and consider:
>
> * Caching results for frequently accessed time periods
> * Using broader time ranges to reduce query frequency
> * Implementing request queuing for multiple statistics calls

## Sending Limits

Hourly sending limits start low for new accounts and grow with account age, plan and sending reputation; support can raise them. These are separate from API request rates and the Free plan's 1,000 included emails per month. See [plans and limits](https://ahasend.com/docs/facts.md).

## Contact Support

If your application requires higher rate limits due to legitimate high-volume usage patterns, please contact our support team to discuss custom rate limit arrangements.

> [card] Need Higher Limits?
>
> Reach out to our [support team](mailto:support@ahasend.com) if you need increased rate limits for your production application.

## Related Guides

* [API authentication](https://ahasend.com/docs/api-reference/authentication.md), [Permission scopes](https://ahasend.com/docs/api-reference/scopes.md), [Send-only API keys](https://ahasend.com/docs/send-api/credentials.md).
* [REST sending guide](https://ahasend.com/docs/send-api/send-email.md), [SMTP settings](https://ahasend.com/docs/smtp.md), [CLI quickstart](https://ahasend.com/docs/cli/quickstart.md).
* [Node.js SDK](https://ahasend.com/docs/guides/nodejs-sdk.md), [Go SDK](https://ahasend.com/docs/guides/go-sdk.md), [API errors](https://ahasend.com/docs/api-reference/errors.md).
* [Suppression durations](https://ahasend.com/docs/bounces.md#suppression-duration).


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