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 and by carrier-side throughput 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) | Roughly 3 messages/second |
| Canadian local number | Just under 1 message/second per number, best-effort |
Flare queues campaign messages that exceed these limits rather than dropping them — large campaigns simply take longer to drain. For faster sending to Canada, use a toll-free number; 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.