Anyone who's built on top of social media service APIs knows the pattern. You fire off ten orders, three time out, two come back with "rate limit exceeded" and your customers are refreshing the page wondering what happened.
The fix isn't clever. It's a queue. Here's a minimal one in Python that's good enough for a small reseller tool or a Telegram bot.
The problem
Most SMM-style APIs share a shape: one endpoint, a key, an action (add, status, balance, refill) and form-encoded params. They also share limits. Hammer them and you get throttled, or worse, duplicate orders when you retry a request that actually succeeded.
A tiny queue with idempotency
import time, uuid, sqlite3, requests
API_URL = "https://YOUR-PANEL/api/v2"
API_KEY = "env-var-please"
MIN_GAP = 1.5 # seconds between calls
db = sqlite3.connect("queue.db")
db.execute("""CREATE TABLE IF NOT EXISTS jobs (
id TEXT PRIMARY KEY, service INT, link TEXT, qty INT,
status TEXT DEFAULT 'pending', order_id INT, tries INT DEFAULT 0)""")
def enqueue(service, link, qty):
job_id = str(uuid.uuid4())
db.execute("INSERT INTO jobs (id, service, link, qty) VALUES (?,?,?,?)",
(job_id, service, link, qty))
db.commit()
return job_id
def worker():
while True:
row = db.execute("SELECT id, service, link, qty, tries FROM jobs "
"WHERE status='pending' ORDER BY rowid LIMIT 1").fetchone()
if not row:
time.sleep(5); continue
job_id, service, link, qty, tries = row
try:
r = requests.post(API_URL, data={"key": API_KEY, "action": "add",
"service": service, "link": link, "quantity": qty}, timeout=30)
data = r.json()
if "order" in data:
db.execute("UPDATE jobs SET status='sent', order_id=? WHERE id=?",
(data["order"], job_id))
else:
db.execute("UPDATE jobs SET status='failed', tries=? WHERE id=?",
(tries + 1, job_id))
except requests.Timeout:
# don't blindly retry: check status first to avoid duplicates
db.execute("UPDATE jobs SET status='check', tries=? WHERE id=?",
(tries + 1, job_id))
db.commit()
time.sleep(MIN_GAP)
The important bits
- One worker, fixed gap. Simple, predictable, nowhere near any rate limit.
-
Timeouts go to
check, notpending. A timeout doesn't mean the order failed. Reconcile against your panel's order history before retrying, or you'll double-charge. - SQLite is enough. You don't need Redis for a few hundred orders a day.
- Keep the key out of the code. Environment variables, always.
Trying it against a real API
If you want something concrete to point this at, BoostingPH is a Philippine panel with the standard v2-style endpoints documented at https://www.boostingph.com/api. And if you're building for Filipino businesses, their social media marketing guide for the Philippines is good background on what your end users are actually trying to achieve.
Queue it. Space it. Reconcile before retrying.
MD Fozla Rabbi, SEO Specialist
Top comments (0)