Skip to content

Rate limits

Lisoloo applies per-API-key rate limits on every endpoint. Exceeding a limit returns 429 Too Many Requests with a Retry-After header and error_code: 1301 RATE_LIMIT_EXCEEDED in the body.

EndpointLimitWindowNotes
POST /send60 requestsper minuteEach request can hit many recipients — this counts requests, not SMS.
GET /status/{message_id}120 requestsper minuteHigher cap so polling loops don’t get throttled.
GET /balance30 requestsper minuteRead-heavy, but rarely needed more than once a minute.
GET /healthunlimitedUnauthenticated, no bucket.

Buckets are independent per key. Sandbox and production keys have the same caps.

HTTP/1.1 429 Too Many Requests
Content-Type: application/json
Retry-After: 27
{
"success": false,
"status_code": 429,
"error_code": "1301",
"message": "Rate limit exceeded",
"retry_after": 27
}

Retry-After is in seconds (the same value also appears in the JSON body as retry_after). Wait at least that long before retrying. Retrying earlier returns another 429 with a fresh Retry-After.

The correct retry pattern is wait, then retry once. Don’t loop on 429s — at best you waste your bucket, at worst you trigger 1302 SUSPICIOUS_ACTIVITY and your key gets a temporary suspension.

import time
import requests
def send_with_retry(payload, max_attempts=3):
for attempt in range(max_attempts):
r = requests.post(SEND_URL, headers=HEADERS, json=payload, timeout=10)
if r.status_code != 429:
return r
delay = int(r.headers.get("Retry-After", 60))
time.sleep(delay)
r.raise_for_status()
async function sendWithRetry(payload, maxAttempts = 3) {
for (let attempt = 0; attempt < maxAttempts; attempt++) {
const r = await fetch(SEND_URL, {
method: "POST",
headers: HEADERS,
body: JSON.stringify(payload),
});
if (r.status !== 429) return r;
const delay = parseInt(r.headers.get("Retry-After") ?? "60", 10);
await new Promise(res => setTimeout(res, delay * 1000));
}
throw new Error("rate-limited after retries");
}

If you are sending to thousands of recipients, batch into one call rather than looping. A single POST /send with a 1 000-element to array is one rate-limit hit; 1 000 separate calls is 1 000 hits.

Hard caps per request:

  • to: up to 1 000 recipients per call.
  • scheduled_dates: up to 20 dates per call.
  • recurring_schedule: pre-computed total ≤ 5 000 future SMS.

For larger volumes, batch into multiple calls spaced ≥1 second apart, or contact your Bloonio account manager for a per-merchant cap increase.

The rate-limit window resets continuously, not on a fixed second boundary. A naive “send 60 messages at 00:00:00” + “send 60 more at 00:01:00” pattern can still trigger 429 if the burst at :01 overlaps the window. Spread the load over the minute or honour Retry-After.