Rate Limits
Rate Limits
Section titled “Rate Limits”The SIPSTACK API enforces rate limits to keep the platform stable. Limits are applied per client over fixed windows; sensitive operations have stricter, dedicated limits.
Current Limits
Section titled “Current Limits”| Operation | Limit |
|---|---|
Flare API requests (/flare/*, messages, contacts, webhooks), per organization | By plan: Pro 60 / minute, Ultra 300 / minute, Enterprise unlimited |
Other API requests (Nova, Aura, numbers, /me, /calls), per API key | 100 requests / minute |
| SMS sending endpoints | 30 sends / minute |
| Login attempts | 20 / 15 minutes per IP, plus 3 failed attempts / 30 minutes per email |
| Password reset requests | 3 / hour |
| Two-factor verification | 10 / 15 minutes |
| Data exports | 10 / hour |
Plan Message Limits
Section titled “Plan Message Limits”Separately from request rate limits, sending through POST /api/v2/messages/send is subject to your plan’s SMS limits. When one is reached, the send is refused and nothing is sent or counted. The body carries a code, and for some refusals a reason:
{ "success": false, "code": "PAID_LIMIT_REACHED", "reason": "daily", "error": "Daily send limit of 2500 segments reached."}| Status | code | reason | Meaning | What to do |
|---|---|---|---|---|
429 | PAID_LIMIT_REACHED | daily | Daily send limit reached | Wait for Retry-After (the next 00:00 UTC) |
429 | PAID_LIMIT_REACHED | monthly_absolute | Monthly safety ceiling (3× your outbound allowance) reached | Wait for Retry-After (your next pool reset) |
429 | PAID_LIMIT_REACHED | new_account_velocity | New-account limit (2,000 segments in the first 72 hours) reached | Wait for Retry-After |
429 | TRIAL_LIMIT_REACHED | lifetime | Trial message limit reached | Activate your plan — retrying won’t help |
429 | TRIAL_LIMIT_REACHED | burst | More than 50 messages in 10 minutes during a trial | Slow down and retry in a few minutes |
403 | CARD_NOT_VERIFIED | — | The send would go beyond your included allowance and no valid payment method is on file | Add a card on Account → Billing |
402 | CAPABILITY_RESTRICTED_BY_STATE | — | The send would go beyond your included allowance and the subscription is past due or scheduled to cancel | Pay the open invoice or undo the cancellation |
503 | TRIAL_LIMIT_REACHED | — | A limit couldn’t be checked right now | Retry after a short backoff |
Honor Retry-After. On a PAID_LIMIT_REACHED response, Retry-After gives the number of seconds until the limit lifts, which can be hours or days away. Don’t retry in a loop. Queue the message and send it after that time, or report the failure to your user. A 429 without Retry-After is either a trial limit (see the table) or the request rate limit below; for the rate limit, back off using RateLimit-Reset.
Branch on the HTTP status first and use code and reason to refine it. A 503 carries TRIAL_LIMIT_REACHED as its code, but it means “try again shortly”, not “limit reached”.
How pools, limits, and overage work: SMS Usage, Limits & Billing. Your usage is on the Flare dashboard.
Rate Limit Headers
Section titled “Rate Limit Headers”Responses include the standard RateLimit-* headers:
RateLimit-Limit: 100RateLimit-Remaining: 87RateLimit-Reset: 42| Header | Description |
|---|---|
RateLimit-Limit | Maximum requests in the current window |
RateLimit-Remaining | Requests left in the window |
RateLimit-Reset | Seconds until the window resets |
Read these in your client to throttle proactively instead of hitting the limit.
When the Limit Is Exceeded
Section titled “When the Limit Is Exceeded”Exceeding a limit returns HTTP 429 Too Many Requests with a plain-text or JSON message describing which limit you hit. Do not retry immediately. If the response has a Retry-After header (the Flare API request limit, or an SMS plan limit), wait at least that long. Otherwise wait for the window to reset (RateLimit-Reset) and use exponential backoff on consecutive 429s:
async function apiRequest(url, options, maxRetries = 3) { for (let attempt = 0; attempt <= maxRetries; attempt++) { const response = await fetch(url, options);
if (response.status !== 429) return response; if (attempt === maxRetries) throw new Error('Rate limited after max retries');
// An SMS plan limit says exactly when it lifts — often hours away. // Don't hold the request open; hand it back to your queue instead. const retryAfter = response.headers.get('Retry-After'); if (retryAfter && Number(retryAfter) > 300) return response;
const reset = Number(retryAfter ?? response.headers.get('RateLimit-Reset') ?? 60); const delay = Math.min(reset * Math.pow(2, attempt) * 1000, 300_000); await new Promise((r) => setTimeout(r, delay)); }}Carrier Throughput (SMS)
Section titled “Carrier Throughput (SMS)”Beyond API limits, SMS delivery speed is bounded by your Flare plan’s send speed (up to 2, 4 or 8 message segments per second on Core, Pro and Ultra, 20+ on Enterprise, across your account) and by the limit for the number type — whichever is lower. Carrier limits cannot be raised by SIPSTACK:
| Number type | Approximate throughput |
|---|---|
| US 10DLC (registered) | Depends on your brand’s trust score and campaign — see your 10DLC campaign |
| Toll-free (verified) | Up to 3 messages/second |
| Canadian local number | Up to 9 message segments/second per number (SIPSTACK pacing, not a carrier limit) |
Flare queues campaign messages that exceed these limits rather than dropping them — large campaigns simply take longer to drain. For US 10DLC, enhanced brand vetting is the usual lever. See Sending Speeds for messages per hour by plan and number type.
Best Practices
Section titled “Best Practices”- Cache static data — extension lists and configuration change rarely; don’t re-fetch on every request.
- Paginate efficiently — request the maximum page size instead of one record at a time.
- Throttle on
RateLimit-Remaining— back off before the limit, not after. - Queue your sends — for bulk SMS, feed a queue at a steady rate instead of bursting.