Reseller API
Wholesale access for agencies and resellers. Create sub-accounts for your own customers, provision subscriptions against your reseller balance at wholesale prices, generate proxy lists, and track usage and live connections, all over a REST API under one approved reseller account.
Base URL
All Reseller API requests go to:
https://dashboard.proxyomega.com/api/reseller/v1
Every endpoint path on this page is relative to this base. All responses are application/json. A no-auth test sandbox is available under /dev.
Getting access
Three steps stand between a regular account and live Reseller API access:
- Apply for a reseller account. Apply from the dashboard. Applications are reviewed and approved manually. Learn more at proxyomega.com/reseller-program.
- Complete identity verification (KYC). Every production endpoint except the
/kyc/*and/balance/*routes returns401until your identity is verified. Start verification via the API (see Identity verification) or in the dashboard. - Fund your reseller balance. Provisioning is wallet-based: every purchase is charged to your reseller balance at wholesale price. Move funds from your main account balance with
POST /balance/transfer. The first transfer requires verified KYC and activates the account.
Authentication
Send your API key in the X-API-Key header on every request:
X-API-Key: YOUR_API_KEY
A bearer token is also accepted, so Authorization: Bearer YOUR_API_KEY works with the same key. The key is your ProxyOmega account API key, viewable and regenerable in the dashboard once your reseller account is approved.
curl https://dashboard.proxyomega.com/api/reseller/v1/balance \
-H "X-API-Key: YOUR_API_KEY" \
-H "Accept: application/json"
Responses & envelope
Every endpoint wraps its payload in the same envelope. Successful calls return:
{
"success": true,
"data": { },
"message": "Optional human-readable note"
}
Errors return "success": false with an explanation:
{
"success": false,
"error": "Description of what went wrong"
}
Always check success before reading data. Validation failures may include a per-field errors object.
Rate limits
The default limit is 100 requests per minute over a sliding 60-second window. Exceeding it returns 429. Every response carries the current state in headers:
| Header | Meaning |
|---|---|
X-RateLimit-Limit | Your requests-per-minute allowance |
X-RateLimit-Remaining | Requests left in the current window |
X-RateLimit-Used | Requests used in the current window |
X-RateLimit-Reset | Unix timestamp when the window resets |
Account, balance & transactions
| Method | Endpoint | Purpose |
|---|---|---|
GET | / | API version plus a summary of your reseller ID, tier, and balance |
GET | /balance | Balance, tier, discount, monthly spending, and tier thresholds |
POST | /balance/transfer | Move funds from your main account balance to your reseller balance |
GET | /transactions | Paginated ledger of every charge and credit on the reseller balance |
Check your balance
curl https://dashboard.proxyomega.com/api/reseller/v1/balance \
-H "X-API-Key: YOUR_API_KEY"
{
"success": true,
"data": {
"balance": 250.00,
"tier": "silver",
"current_discount": "15%",
"monthly_spending": 1240.50,
"spending_reset_date": "2026-08-01",
"next_tier": "gold",
"amount_to_next_tier": 759.50,
"minimum_balance_required": 100.00
}
}
Your tier (bronze, silver, gold, platinum) is driven by monthly spending, and the tier's discount is already applied to the wholesale prices you see in the catalog and pay at provisioning time.
Fund the reseller balance
POST /balance/transfer with a JSON body of {"amount": 250}. Transfers are between $100 (minimum, and the first transfer activates your account) and $10,000 per transfer, and are atomic: either the full amount moves or nothing does.
curl -X POST https://dashboard.proxyomega.com/api/reseller/v1/balance/transfer \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"amount": 250}'
The response includes new_reseller_balance, new_main_balance, and is_first_transfer. A first transfer without verified KYC returns 403 with kyc_required: true; an amount your main balance cannot cover returns 400 with the available, requested, and shortfall figures.
Transaction history
GET /transactions accepts page (default 1), limit (10 to 100, default 20), and an optional type filter: deposit, provision, refund, or adjustment (renewal and upgrade rows also appear in the data). Each row carries the amount, balance before and after, the related sub-account and subscription, and a description, plus a pagination block.
Identity verification (KYC)
The /kyc/* routes work before verification so you can complete it entirely over the API. Verification uses a hosted flow: you submit a government document (passport, driving licence, or ID card) and a matching selfie at a secure URL, then poll the status.
| Method | Endpoint | Purpose |
|---|---|---|
GET | /kyc/status | Current verification status and attempts remaining |
POST | /kyc/business-info | Set company_name (required), company_address (required), tax_id (optional) |
POST | /kyc/start-verification | Create a verification session; returns a hosted url to complete it |
POST /kyc/start-verification (empty body) returns session_id, url, status: "pending", and expires_at. Open the URL to complete verification, then poll GET /kyc/status. Status values: not_started, pending, processing, verified, rejected, expired. You get a maximum of 3 attempts; after that the endpoint returns 403 and you should contact support.
Products, capacity & locations
| Method | Endpoint | Purpose |
|---|---|---|
GET | /products | Wholesale catalog with retail and wholesale prices per plan |
GET | /capacity | Per-tier availability pre-flight for Budget Unlimited |
GET | /geographic/countries | Countries available for a product (product_type required) |
GET | /geographic/regions | Regions within a country (Residential/ISP and Mobile) |
GET | /geographic/cities | Cities within a country or region |
Catalog
GET /products returns your tier, discount_percentage, and per-product pricing. Each pricing row includes both retail_price and wholesale_price with your tier discount already applied. The catalog covers:
- unlimited (Budget Unlimited): 5, 15, 25, 50, or 100 ports, for
1_day,7_days, or30_days - ipv6: 100, 250, 500, or 1000 threads, same three durations
- platinum (Residential/ISP) and mobile: pay-as-you-go bandwidth tiers from 1 GB to 1000 GB
GET /products. Contact [email protected] or check your dashboard for Premium wholesale pricing.Capacity
GET /capacity is a pre-flight check before selling Budget Unlimited: it returns {"tiers": [{"ports": 5, "available": ...}, ...], "as_of": "..."} so you can confirm a port tier is available before provisioning. If a tier is temporarily unavailable at purchase time, provisioning returns 409.
Locations
GET /geographic/countries?product_type=platinum lists countries as {code, name} pairs, plus supports_regions and supports_cities flags. product_type is required and accepts platinum, mobile, ipv6, unlimited, or premium_unlimited. For platinum and mobile the first entry has an empty code, meaning random/default.
GET /geographic/regions?product_type=platinum&country=US lists regions (Residential/ISP and Mobile only). GET /geographic/cities?product_type=platinum&country=US®ion=California lists cities; region is optional, and cities are also available for premium_unlimited (without region).
Sub-accounts
Sub-accounts are the accounts you hand to your own customers. Each gets its own proxy username and password, its own subscriptions, whitelist, and usage history.
| Method | Endpoint | Purpose |
|---|---|---|
GET | /sub-accounts | List sub-accounts with subscription and usage summaries |
POST | /sub-accounts | Create a sub-account |
GET | /sub-accounts/{id} | Full detail: subscriptions, bandwidth purchases, whitelist, proxy credentials |
PUT | /sub-accounts/{id} | Update email, label, external_id, or status (active | suspended) |
DELETE | /sub-accounts/{id} | Soft-delete; all active subscriptions are cancelled |
POST | /sub-accounts/{id}/regenerate-password | Rotate the sub-account's proxy password/API key |
Create a sub-account
username is required (3 to 30 characters, letters, digits, and underscores). external_id, email, and label are optional and yours to use for reconciliation with your own systems.
curl -X POST https://dashboard.proxyomega.com/api/reseller/v1/sub-accounts \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"username": "client1",
"email": "[email protected]",
"label": "Client A"
}'
{
"success": true,
"data": {
"id": 512,
"username": "res_42_client1",
"password": "a1b2c3d4e5f6a7b8",
"api_key": "a1b2c3d4e5f6a7b8",
"external_id": null,
"email": "[email protected]",
"label": "Client A",
"status": "active",
"proxy_auth": {
"format": "username:api_key",
"example": "res_42_client1:[email protected]:10000"
}
}
}
Note the returned username is prefixed with res_<your-reseller-id>_. White-label accounts keep the username exactly as submitted; contact support about white-label. The password and api_key are the same value, and this value is what the sub-account uses as its proxy password. Duplicate usernames return 409.
List and inspect
GET /sub-accounts accepts page, limit (10 to 100, default 20), status (active | suspended | deleted), search (matches username, label, email, or external ID), and has_active_subscription=1. Each row includes counts of active subscriptions and bandwidth purchases, whitelisted IPs, per-product summaries, and 24-hour request/bandwidth stats.
GET /sub-accounts/{id} returns everything about one sub-account: each subscription with its proxy connection details (host, port or port range, username, password, ready-to-use full_proxy string), each pay-as-you-go bandwidth purchase with live used/available GB, and the whitelist.
Sub-account, subscription, whitelist, and proxy-list routes accept either the numeric sub-account id or its username in the path. The analytics and connections routes require the numeric id.
Rotate credentials
POST /sub-accounts/{id}/regenerate-password mints a fresh key. The proxy password and API key rotate together, and the new credential is live on the proxy network within about a minute (usually seconds). Requests to a deleted sub-account return 410.
IP whitelists
Each sub-account can whitelist up to 10 IPs (IPv4 or IPv6). Whitelisted IPs can use the proxies without password authentication.
| Method | Endpoint | Purpose |
|---|---|---|
GET | /sub-accounts/{id}/whitelist | List whitelist entries |
POST | /sub-accounts/{id}/whitelist | Add an IP: {"ip_address": "198.51.100.7", "label": "Client server"} |
DELETE | /sub-accounts/{id}/whitelist/{ip_id} | Remove an entry by its id |
Adding an already-whitelisted IP returns 409; the 11th IP returns 400.
Provisioning subscriptions
POST /sub-accounts/{id}/subscriptions provisions a product for a sub-account and charges your reseller balance at your wholesale price. The body depends on the product:
product_type | Required fields | Accepted values |
|---|---|---|
unlimited | duration, ports | 1_day | 7_days | 30_days; ports 5 | 15 | 25 | 50 | 100 |
ipv6 | duration, threads | Same durations; threads 100 | 250 | 500 | 1000 |
platinum | gb | 1 | 5 | 15 | 25 | 50 | 100 | 150 | 200 | 500 | 1000 |
mobile | gb | Same GB tiers |
premium_unlimited | duration, speed_mbps, location_id | Mbps 200 | 250 | 400 | 500 | 600 | 750 | 800 | 1000 |
curl -X POST https://dashboard.proxyomega.com/api/reseller/v1/sub-accounts/512/subscriptions \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"product_type": "unlimited",
"duration": "30_days",
"ports": 25
}'
{
"success": true,
"data": {
"subscription_id": 90411,
"product_type": "unlimited",
"wholesale_price": 100.00,
"balance_remaining": 400.00,
"date_expiry": "2026-08-09T14:02:11+00:00",
"status": "active",
"credentials": {
"host": "203.0.113.10",
"port_range": "10000-10024",
"username": "res_42_client1",
"password": "a1b2c3d4e5f6a7b8",
"full_proxy": "http://res_42_client1:[email protected]:10000"
}
}
}
New subscriptions return 201. Insufficient balance returns 400 with the required and available amounts. Credentials become active on the proxy network within about a minute.
unlimited or ipv6 subscription with the same configuration, the call extends that subscription instead of creating a second one: it returns 200 with "action": "renewed" and the new expiry. To change size, use the upgrade endpoint.Pay-as-you-go bandwidth (Residential/ISP and Mobile)
platinum and mobile orders return a purchase_id and gb_added rather than an expiring subscription; the bandwidth does not expire. If provisioning fails on our side, the charge is automatically refunded to your reseller balance.
Premium Unlimited
Premium Unlimited is a dedicated, pending-fulfilment product. The order is accepted with 201 and box_status: "pending"; the connection host stays null until the dedicated server is ready, which is often near-instant and can take up to 6 hours. Orders require a location_id; contact [email protected] for the currently available Premium locations and pricing.
Connection ports by product
| Product | Ports on the returned host |
|---|---|
Budget Unlimited (unlimited) | 10000 to 10000 + ports - 1 (one rotating IP per port) |
IPv6 (ipv6) | 9000 |
Residential/ISP (platinum) | 20228 |
Mobile (mobile) | 20229 |
Premium Unlimited (premium_unlimited) | 8000 (dedicated host once ready) |
Every port serves HTTP, HTTPS, and SOCKS5 on the same host and port. Use the exact host and ports from the credentials block of each provisioning response.
List, cancel, renew, upgrade
| Method | Endpoint | Purpose |
|---|---|---|
GET | /sub-accounts/{id}/subscriptions | All subscriptions and bandwidth purchases with connection details and live usage |
POST | /sub-accounts/{id}/subscriptions/{sub_id}/cancel | Cancel a subscription (no automatic refund; contact support for refund requests) |
POST | /sub-accounts/{id}/subscriptions/{sub_id}/renew | Extend or reactivate: body {"duration": "30_days"} |
POST | /sub-accounts/{id}/subscriptions/{sub_id}/upgrade | Move to a higher tier mid-term |
Renew applies to unlimited, ipv6, and premium_unlimited with duration of 1_day, 7_days, or 30_days. Active subscriptions extend from their current expiry; expired ones reactivate from now. The response includes previous_expiry, new_expiry, days_added, and the wholesale price charged.
Upgrade takes the field matching the product: ports (unlimited), threads (ipv6), or speed_mbps (premium_unlimited), and the new value must be higher than the current one; downgrades are rejected. The price is the prorated difference over the remaining days, and the expiry date does not change. Expired subscriptions must be renewed first.
Port configuration & country targeting (Budget Unlimited)
Budget Unlimited subscriptions expose per-port controls: each port has a rotation interval and a country setting. Defaults are rotation every 5 minutes with worldwide (all) IPs.
| Method | Endpoint | Purpose |
|---|---|---|
GET | /sub-accounts/{id}/subscriptions/{sub_id}/port-configs | Port range, defaults, and any per-port overrides |
POST | /sub-accounts/{id}/subscriptions/{sub_id}/port-configs | Create or update the config for one port |
DELETE | /sub-accounts/{id}/subscriptions/{sub_id}/port-configs/{config_id} | Remove an override; the port reverts to defaults |
POST | /sub-accounts/{id}/subscriptions/{sub_id}/country-targeting | Set the country for all ports at once: {"country_targeting": "US"} or "all" |
The POST /port-configs body takes port_number (required, within the subscription's port range), rotation_minutes (1 to 60, default 5), country_targeting (all or an ISO-2 country code, default all), enabled (boolean), and notes (up to 255 characters). It is a strict single-port upsert: only the named port changes, never its siblings. Use the country-targeting endpoint for bulk changes.
Proxy list generation
GET /sub-accounts/{id}/proxy-list produces ready-to-distribute proxy lines for a sub-account. The sub-account must have an active subscription or bandwidth for the requested product (403 otherwise).
| Parameter | Values |
|---|---|
product_type | Required: unlimited | ipv6 | platinum | mobile |
quantity | 1 to 1000 (default 10) |
format | host:port:username:password (default) | host:port | username:password@host:port | http://username:password@host:port | socks5://username:password@host:port | json |
country, state, city, session, ttl | Targeting for ipv6, platinum, and mobile lines; ttl is in minutes |
curl "https://dashboard.proxyomega.com/api/reseller/v1/sub-accounts/512/proxy-list?product_type=platinum&quantity=3&format=http://username:password@host:port&country=us" \
-H "X-API-Key: YOUR_API_KEY"
For ipv6, platinum, and mobile, if you do not pass a session, each line gets its own generated session identifier so each line holds a distinct IP. Targeting parameters are rejected with 400 for unlimited: each Budget Unlimited port already provides its own rotating IP, controlled via port configs.
Analytics
Historical usage per sub-account and across your whole book. All analytics routes require the numeric sub-account id.
| Method | Endpoint | Purpose |
|---|---|---|
GET | /analytics/overview | Aggregate requests, success rate, and bandwidth across all sub-accounts, with per-account rows |
GET | /sub-accounts/{id}/analytics | Full breakdown: summary, top target hosts, status codes, daily usage |
GET | /sub-accounts/{id}/analytics/summary | Compact totals for dashboards |
GET | /sub-accounts/{id}/analytics/usage | Time series; granularity=daily (default) or hourly |
GET | /sub-accounts/{id}/analytics/requests | Per-request log, last 7 days; page, limit 10 to 100 (default 50) |
GET | /sub-accounts/{id}/analytics/ports | Per-port usage: requests, success rate, and bandwidth per port |
All analytics endpoints accept period: 1_day (or today), 7_days (week), 30_days (month, the default), 90_days (quarter), 365_days (year), or all.
Per-port usage
GET /sub-accounts/{id}/analytics/ports?period=30_days answers "which of this customer's ports are actually being used":
{
"success": true,
"data": {
"sub_account_id": 512,
"period": "30_days",
"total_ports": 25,
"total_requests": 184220,
"total_bandwidth_gb": 42.7,
"ports": [
{ "port": 10000, "port_type": "unlimited", "requests": 96410, "successful": 95514, "success_rate": 99.1, "bandwidth_gb": 21.9 },
{ "port": 10001, "port_type": "unlimited", "requests": 87810, "successful": 86733, "success_rate": 98.8, "bandwidth_gb": 20.8 }
]
}
}
Live connections
Real-time and recent-history concurrency monitoring, useful for spotting sub-accounts near their connection limits. Numeric sub-account ids only. Figures can lag by up to about 30 seconds.
| Method | Endpoint | Purpose |
|---|---|---|
GET | /connections/overview | Live utilization across all sub-accounts; window_minutes 1 to 15 (default 5) |
GET | /sub-accounts/{id}/connections | Active connections vs. limit, plus per-port requests/sec and Mbps in/out |
GET | /sub-accounts/{id}/connections/history | Connection history with peak usage |
The overview labels each sub-account idle, active, moderate, or near_limit and flags near_limit_accounts so you can act before customers hit their ceiling. History accepts period (1_hour, 6_hours, 24_hours default, 7_days, 30_days) and granularity (auto default, 5_min, 15_min, 1_hour, 6_hours, 1_day; the finest granularities are available for recent windows only) and includes a peak block with the highest concurrency and when it happened.
Errors
Errors use the standard envelope ("success": false plus an error string) with conventional HTTP status codes:
| Status | Meaning |
|---|---|
400 | Validation error, unsupported value, or insufficient balance (includes required vs. available amounts) |
401 | Missing or invalid API key, KYC verification required, or account suspended |
403 | Action requires verified KYC, or no active subscription for the requested product |
404 | Resource not found |
405 | Method not allowed on this endpoint |
409 | Conflict: duplicate username, IP already whitelisted, or a port tier temporarily unavailable |
410 | The sub-account has been deleted |
429 | Rate limit exceeded; check the X-RateLimit-* headers |
500 / 503 | Server error or a dependency temporarily unavailable; retry with backoff |
{
"success": false,
"error": "Insufficient balance. Required: $100.00, Available: $25.00"
}
Test sandbox
A full mock of the API is available for integration testing, no authentication required:
https://dashboard.proxyomega.com/api/reseller/v1/dev
The sandbox mirrors the production paths and response envelopes, returns mock data, and marks every response with "_dev_mode": true. Nothing is created and nothing is charged. Mock error scenarios are supported so you can exercise your error handling.
GET /products endpoint.How to become a reseller
Related
- Public API. Self-service API for managing your own account.
- Authentication. The three ways to authenticate proxy connections.
- Targeting. Country, state, city, ASN, session, and TTL parameters.
- Sessions & rotation. How sticky sessions and rotation behave per product.
Last updated July 10, 2026