Reseller Integration
Build a proxy reselling business on top of the RedScrape API automate purchasing, manage customers, and monitor usage at scale.
There is now a dedicated Reseller API with first-class customer packages: one call provisions a package with its own credentials, traffic limit and lifecycle, and you can suspend or top it up per customer. Prefer it for new integrations. This guide covers the older pattern of reselling through your own subscriptions, which still works.
Overview
The RedScrape public API lets you build a full reseller platform. You can programmatically purchase proxies, manage subscriptions for your customers, monitor data usage, and automate renewals all through API calls authenticated with your API key.
Architecture
A typical reseller integration looks like this:
- Your platform your own dashboard or application where end customers sign up
- RedScrape API backend proxy infrastructure you purchase from
- Your customers use proxies provisioned through your platform
Your backend acts as a middleware between your customers and the RedScrape API.
Bulk Purchasing
Buying Plans for Customers
When a customer orders a proxy through your platform, call the purchase endpoint:
import requests
API_KEY = "your_reseller_api_key"
BASE = "https://api.redscrape.com/api/public"
HEADERS = {"X-API-Key": API_KEY, "Content-Type": "application/json"}
def provision_proxy(product_slug, billing_period, threads=100, data_gb=50):
"""Purchase a new proxy plan."""
resp = requests.post(f"{BASE}/payments/purchase", headers=HEADERS, json={
"product_slug": product_slug,
"billing_period": billing_period,
"payment_method": "wallet",
"threads": threads,
"data_gb": data_gb,
})
resp.raise_for_status()
return resp.json()
# Provision a monthly datacenter proxy
invoice = provision_proxy("datacenter-proxy", "monthly", threads=200, data_gb=100)
print(f"Invoice #{invoice['id']} Status: {invoice['status']}")Getting Proxy Credentials
Use the dedicated credentials endpoint for quick access:
def get_credentials(sub_id):
"""Get proxy connection details host, port, user, pass, connection string."""
resp = requests.get(f"{BASE}/subscriptions/{sub_id}/credentials", headers=HEADERS)
resp.raise_for_status()
return resp.json()
creds = get_credentials(42)
print(f"Connection: {creds['connection_string']}")
print(f"Location: {creds['node']['location']} ({creds['node']['country_code']})")Bulk Export All Credentials
Export all active proxy credentials in one call perfect for syncing with your system:
def export_all_proxies(format="json"):
"""Export all active proxy credentials."""
resp = requests.get(
f"{BASE}/subscriptions/export/credentials",
headers=HEADERS,
params={"format": format, "status": "active"},
)
resp.raise_for_status()
if format == "plain":
return resp.text # host:port:user:pass per line
return resp.json()
# JSON format full details
data = export_all_proxies("json")
for proxy in data["proxies"]:
print(f"[{proxy['nickname']}] {proxy['connection_string']}")
# Plain text one proxy per line (great for tools that accept proxy lists)
proxy_list = export_all_proxies("plain")
print(proxy_list)
# us.proxy.redscrape.com:10000:user_abc:pass123
# eu.proxy.redscrape.com:10000:user_def:pass456Customer Management
Labeling Subscriptions
Use nicknames to map subscriptions to your internal customer IDs:
def assign_to_customer(sub_id, customer_id):
"""Label a subscription with a customer identifier."""
resp = requests.patch(
f"{BASE}/subscriptions/{sub_id}/rename",
headers=HEADERS,
json={"nickname": f"customer_{customer_id}"}
)
resp.raise_for_status()Filtering Subscriptions
List subscriptions with filters to find specific proxies:
def get_active_datacenter_proxies():
"""Get all active datacenter subscriptions."""
resp = requests.get(
f"{BASE}/subscriptions/",
headers=HEADERS,
params={"status": "active", "category_slug": "datacenter"},
)
resp.raise_for_status()
return resp.json()
result = get_active_datacenter_proxies()
for sub in result["items"]:
proxy = sub["proxy"]
print(f"[{sub['nickname']}] {proxy['proxy_host']}:{proxy['proxy_port']}")
print(f" Region: {proxy['node']['location']} ({proxy['node']['country_code']})")
print(f" Data: {proxy['data_usage_percent']}% used")
print(f" Expires: {sub['time_remaining_human']}")IP Whitelisting
If your customers use IP-based authentication, manage their allowed IPs:
def whitelist_customer_ip(sub_id, ip_address, label=""):
"""Add a customer's IP to the proxy whitelist."""
resp = requests.post(
f"{BASE}/subscriptions/{sub_id}/ip-whitelist",
headers=HEADERS,
json={"ip_address": ip_address, "label": label}
)
resp.raise_for_status()
return resp.json()
def remove_customer_ip(sub_id, ip_id):
"""Remove an IP from the whitelist."""
resp = requests.delete(
f"{BASE}/subscriptions/{sub_id}/ip-whitelist/{ip_id}",
headers=HEADERS,
)
resp.raise_for_status()Password Rotation
Rotate proxy passwords when a customer requests it or on a schedule:
def rotate_password(sub_id):
"""Reset proxy password for a subscription."""
resp = requests.post(
f"{BASE}/subscriptions/{sub_id}/reset-password",
headers=HEADERS,
)
resp.raise_for_status()
return resp.json()["proxy_password"]Usage Monitoring
Dedicated Usage Endpoint
Use the /usage endpoint for detailed consumption data:
def get_usage(sub_id):
"""Get detailed usage stats data, time, limits."""
resp = requests.get(f"{BASE}/subscriptions/{sub_id}/usage", headers=HEADERS)
resp.raise_for_status()
return resp.json()
usage = get_usage(42)
print(f"Data: {usage['data']['used_gb']} / {usage['data']['max_gb']} GB ({usage['data']['usage_percent']}%)")
print(f"Remaining: {usage['data']['remaining_gb']} GB")
print(f"Time left: {usage['time']['remaining_days']} days")
print(f"Threads: {usage['limits']['threads']}")
print(f"IPs whitelisted: {usage['limits']['whitelisted_ips_count']}/{usage['limits']['max_ips'] or '∞'}")Monitor All Subscriptions
The list endpoint includes usage data inline no extra calls needed:
def monitor_all(threshold=0.8):
"""Check all active subscriptions for those nearing data limits."""
resp = requests.get(
f"{BASE}/subscriptions/",
headers=HEADERS,
params={"status": "active"},
)
resp.raise_for_status()
alerts = []
for sub in resp.json()["items"]:
proxy = sub.get("proxy")
if not proxy or not proxy.get("data_usage_percent"):
continue
if proxy["data_usage_percent"] >= threshold * 100:
alerts.append({
"sub_id": sub["id"],
"nickname": sub["nickname"],
"usage_percent": proxy["data_usage_percent"],
"remaining_bytes": proxy["data_remaining_bytes"],
"expires": sub["time_remaining_human"],
})
return alertsAuto Top-Up
Automatically add data when usage exceeds a threshold:
def auto_topup(sub_id, topup_gb=50, threshold=0.9):
"""Top-up data if usage exceeds threshold."""
usage = get_usage(sub_id)
if usage["data"] and usage["data"]["usage_percent"] and usage["data"]["usage_percent"] >= threshold * 100:
resp = requests.post(
f"{BASE}/subscriptions/{sub_id}/topup-data",
headers=HEADERS,
json={"data_gb": topup_gb},
)
resp.raise_for_status()
return {"topped_up": True, "new_max_bytes": resp.json()["new_max_data_bytes"]}
return {"topped_up": False}Pricing & Margins
Calculating Your Cost
Use the price calculator before purchasing to determine your cost:
def get_cost(product_slug, billing_period, threads=100, data_gb=50, coupon=None):
"""Calculate the cost for a plan."""
body = {
"product_slug": product_slug,
"billing_period": billing_period,
"threads": threads,
"data_gb": data_gb,
}
if coupon:
body["coupon_code"] = coupon
resp = requests.post(f"{BASE}/payments/calculate-price", json=body)
resp.raise_for_status()
return resp.json()Maintaining Your Wallet
Keep your wallet funded to ensure uninterrupted provisioning:
def check_balance():
"""Check current wallet balance."""
resp = requests.get(f"{BASE}/account/balance", headers=HEADERS)
resp.raise_for_status()
return float(resp.json()["balance"])
def deposit(amount, method="stripe"):
"""Deposit funds into your wallet."""
resp = requests.post(
f"{BASE}/payments/deposit",
headers=HEADERS,
json={"amount": amount, "payment_method": method},
)
resp.raise_for_status()
return resp.json()Full Example: Reseller Bot
Here's a complete example combining all the concepts:
import requests
import time
API_KEY = "your_reseller_api_key"
BASE = "https://api.redscrape.com/api/public"
HEADERS = {"X-API-Key": API_KEY, "Content-Type": "application/json"}
class ResellerClient:
def provision(self, product, period, threads, data_gb, customer_id):
"""Provision a new proxy for a customer."""
# 1. Purchase the plan
invoice = requests.post(f"{BASE}/payments/purchase", headers=HEADERS, json={
"product_slug": product,
"billing_period": period,
"payment_method": "wallet",
"threads": threads,
"data_gb": data_gb,
}).json()
# 2. Get the latest subscription
subs = requests.get(
f"{BASE}/subscriptions/",
headers=HEADERS,
params={"status": "active"},
).json()
new_sub = subs["items"][0]
# 3. Label it with customer ID
requests.patch(
f"{BASE}/subscriptions/{new_sub['id']}/rename",
headers=HEADERS,
json={"nickname": f"cust_{customer_id}"}
)
# 4. Get credentials
creds = requests.get(
f"{BASE}/subscriptions/{new_sub['id']}/credentials",
headers=HEADERS,
).json()
return {
"subscription_id": new_sub["id"],
"connection_string": creds["connection_string"],
"proxy_host": creds["proxy_host"],
"proxy_port": creds["proxy_port"],
"username": creds["proxy_username"],
"password": creds["proxy_password"],
"location": creds["node"]["location"] if creds["node"] else None,
"invoice_id": invoice["id"],
}
def get_customer_usage(self, sub_id):
"""Get usage summary for a customer's proxy."""
usage = requests.get(
f"{BASE}/subscriptions/{sub_id}/usage",
headers=HEADERS,
).json()
return {
"data_used_gb": usage["data"]["used_gb"] if usage["data"] else 0,
"data_remaining_gb": usage["data"]["remaining_gb"] if usage["data"] else None,
"usage_percent": usage["data"]["usage_percent"] if usage["data"] else 0,
"days_remaining": usage["time"]["remaining_days"] if usage["time"] else None,
"is_expired": usage["time"]["is_expired"] if usage["time"] else False,
}
def export_proxy_list(self):
"""Get plain text proxy list for tools that accept host:port:user:pass format."""
resp = requests.get(
f"{BASE}/subscriptions/export/credentials",
headers=HEADERS,
params={"format": "plain", "status": "active"},
)
resp.raise_for_status()
return resp.text
def monitor_all(self, topup_gb=50, threshold=0.85):
"""Check all subscriptions and auto-topup if needed."""
subs = requests.get(
f"{BASE}/subscriptions/",
headers=HEADERS,
params={"status": "active"},
).json()
alerts = []
for sub in subs["items"]:
proxy = sub.get("proxy")
if not proxy or not proxy.get("data_usage_percent"):
continue
if proxy["data_usage_percent"] >= threshold * 100:
requests.post(
f"{BASE}/subscriptions/{sub['id']}/topup-data",
headers=HEADERS,
json={"data_gb": topup_gb},
)
alerts.append(f"Topped up {sub['nickname'] or sub['id']} with {topup_gb} GB")
return alerts
# Usage
client = ResellerClient()
# Provision proxy for customer #1234
proxy = client.provision("datacenter-proxy", "monthly", 100, 50, "1234")
print(f"Proxy ready: {proxy['connection_string']}")
# Check usage
usage = client.get_customer_usage(proxy["subscription_id"])
print(f"Used: {usage['data_used_gb']} GB, Remaining: {usage['data_remaining_gb']} GB")
# Export all proxies for external tools
print(client.export_proxy_list())
# Run monitoring loop
while True:
alerts = client.monitor_all()
for alert in alerts:
print(alert)
time.sleep(300) # Check every 5 minutesBest Practices
- Use the
/credentialsendpoint instead of parsing full subscription objects, use the dedicated endpoint for clean integration - Use
/usagefor monitoring it returns pre-calculated GB, percentages, and time remaining - Export in bulk use
/export/credentials?format=plainto generate proxy lists for tools - Filter with query params use
status,product_slug, andcategory_slugto narrow results - Keep your wallet funded purchases fail if the wallet balance is insufficient
- Use nicknames map subscriptions to your internal customer IDs for easy tracking
- Monitor proactively check data usage regularly and auto-topup before limits are hit
- Rotate API keys periodically use
POST /account/rotate-api-keyand update your stored key - Handle errors all endpoints return standard HTTP error codes; implement retry logic for 5xx errors
- Secure your API key store it in environment variables, never in client-side code