Skip to main content
The Chirp API enforces rate limits to ensure fair usage and maintain service quality for all users.

Rate Limit Tiers

Rate limits vary by endpoint and API key type: App Keys
  • SMS Sending: 100 requests per minute
  • Webhook Management: 60 requests per minute
  • General API: 120 requests per minute
Admin Keys
  • Application Management: 60 requests per minute
  • Organization Settings: 60 requests per minute
  • General API: 120 requests per minute

Rate Limit Headers

Each API response includes headers indicating your current rate limit status:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1640995200
X-RateLimit-Limit The maximum number of requests allowed in the current window. X-RateLimit-Remaining The number of requests remaining in the current window. X-RateLimit-Reset Unix timestamp when the rate limit window resets.

Rate Limit Exceeded

When you exceed the rate limit, the API returns: HTTP Status: 429 Too Many Requests Response:
{
  "error": "Rate limit exceeded. Try again in 30 seconds."
}
Headers:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1640995200
Retry-After: 30

Best Practices

1. Implement Exponential Backoff When you receive a 429 response, wait before retrying:
async function sendWithRetry(payload, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      const response = await fetch(`$https://api.buildwithchirp.com/v1/sms`, {
        method: "POST",
        headers: {
          Authorization: `Bearer ${apiKey}`,
          "Content-Type": "application/json",
        },
        body: JSON.stringify(payload),
      });

      if (response.status === 429) {
        const retryAfter = response.headers.get("Retry-After");
        await new Promise((r) => setTimeout(r, retryAfter * 1000));
        continue;
      }

      return await response.json();
    } catch (error) {
      if (i === maxRetries - 1) throw error;
      await new Promise((r) => setTimeout(r, Math.pow(2, i) * 1000));
    }
  }
}
2. Monitor Rate Limit Headers Track your usage by checking rate limit headers:
const response = await fetch(`$https://api.buildwithchirp.com/v1/sms`, options);

const limit = response.headers.get("X-RateLimit-Limit");
const remaining = response.headers.get("X-RateLimit-Remaining");
const reset = response.headers.get("X-RateLimit-Reset");

console.log(`${remaining}/${limit} requests remaining`);
console.log(`Resets at ${new Date(reset * 1000)}`);
3. Batch Requests When Possible Send messages to multiple recipients in a single request:
{
  "from": "+15551234567",
  "to": ["+15559876543", "+15551112222", "+15553334444"],
  "text": "Bulk message"
}
4. Implement Request Queuing Use a queue to manage high-volume sending:
class RateLimitedQueue {
  constructor(requestsPerMinute) {
    this.queue = [];
    this.interval = 60000 / requestsPerMinute;
  }

  async add(fn) {
    return new Promise((resolve, reject) => {
      this.queue.push({ fn, resolve, reject });
      if (this.queue.length === 1) {
        this.process();
      }
    });
  }

  async process() {
    while (this.queue.length > 0) {
      const { fn, resolve, reject } = this.queue[0];
      try {
        const result = await fn();
        resolve(result);
      } catch (error) {
        reject(error);
      }
      this.queue.shift();
      if (this.queue.length > 0) {
        await new Promise((r) => setTimeout(r, this.interval));
      }
    }
  }
}
5. Cache When Appropriate Cache responses that don’t change frequently:
  • Webhook configurations
  • Application settings
  • Phone number assignments

Higher Rate Limits

If you need higher rate limits for your use case, contact our sales team to discuss custom limits for your account.

Test Mode

Rate limits also apply to test API keys, but test mode has more generous limits to facilitate development and testing.