Reseller API Reference
The Spyderproxy Reseller API lets approved partners resell our full proxy catalog under their own accounts — manage sub-users, buy and provision residential, mobile, and datacenter proxies, allocate bandwidth, and generate ready-to-use connection strings. Every call is authenticated with your reseller key and billed to your reseller wallet.
Contents — jump to an endpoint
The Spyderproxy Reseller API lets approved partners resell the full Spyderproxy proxy catalog under their own accounts. With it you can inspect your reseller wallet and product catalog at bulk pricing, create and manage sub-users (your own end-customers), purchase and provision proxies across every network we operate — residential, budget residential, mobile/LTE, rotating mobile, datacenter, and rotating datacenter — allocate and reclaim residential bandwidth, generate ready-to-use proxy connection strings, and extend or renew time-based orders. Every purchase draws from your reseller wallet balance.
Getting started
Base URL
https://spyderproxy.com/services/v1/reseller
Authentication
Every request must include your reseller API key in the Authorization header:
Authorization: Token <YOUR_RESELLER_API_KEY>
The key identifies an active reseller account. Requests with a missing, invalid, or inactive token are rejected with 401 before the handler runs. Keep this key secret — treat it like a password. Never embed it in client-side code, browser apps, mobile apps, or anything a customer could inspect; all calls should be made from your own backend.
Your first request
Fetch your reseller profile — wallet balance, account id, and residential bandwidth still available in your own pool:
curl -H "Authorization: Token <RESELLER_API_KEY>" \
https://spyderproxy.com/services/v1/reseller/account/
{
"balance": 152.75,
"id": 4021,
"available_traffic": 87.5
}
balance— your reseller wallet balance in account currency (USD). All purchases are debited from this.available_traffic— residential bandwidth (in GB) still available in your own residential sub-user pool. Degrades gracefully to0.0if you have no linked residential sub-user or the provider is unreachable.
Conventions
- Authentication — All endpoints require the
Authorization: Token <RESELLER_API_KEY>header. There are no unauthenticated endpoints. - Content type — Send
Content-Type: application/jsonand a JSON body on allPOSTrequests. - Units — All bandwidth quantities at the API surface are in GB. Internal conversions differ per provider (our residential network uses bytes =
GB × 1024³; the budget residential network uses MB =GB × 1024), but you always send and receive GB. - Money — Reseller purchases draw from your wallet balance. Pricing uses your reseller-specific
ResellerPlanprice when one is configured, otherwise the plan'sbulk_price(the reseller/bulk unit price, not the retail price). - Errors — Errors return an HTTP status with a JSON body carrying either a
detailor amessagefield, e.g.400 {"detail": "..."}or402 {"message": "Insufficient Balance."}. A bad/missing/inactive token returns401. See the Errors section for the full list. - Pagination — List endpoints that are paginated use django-ninja's default LimitOffset scheme: query params
limit(int, default100) andoffset(int, default0), and a response envelope of the form{"items": [...], "count": <int>}. - Async provisioning — Some orders return
status: "In Progress"(or"Pending") while the upstream provider provisions them. PollGET /reseller/orders/{id}/until the status settles to"Completed"and the proxy list is populated.
Account & Products
Mounted at /reseller/.
GET/reseller/account/
Get the authenticated reseller's profile: wallet balance, account id, and residential bandwidth still available in the reseller's own pool.
Request — No path params, query params, or body. Identity comes entirely from the Authorization token.
Response — JSON object:
| Field | Type | Description |
|---|---|---|
balance |
number | The reseller user's wallet balance (USD). |
id |
int | The authenticated reseller account id. |
available_traffic |
float | Residential traffic still available (GB) in the reseller's own sub-user pool. |
available_trafficis resolved live from the residential provider (our residential network). If you have no linked residential sub-user, the sub-user no longer exists at the provider, or the provider call fails, it degrades to0.0rather than erroring.
curl -H "Authorization: Token <RESELLER_API_KEY>" \
https://spyderproxy.com/services/v1/reseller/account/
{
"balance": 152.75,
"id": 4021,
"available_traffic": 87.5
}
GET/reseller/products/
List all sellable products with their reseller-priced plans (the top-up product is excluded).
Request — No path params, query params, or body.
Response — Array of products:
[{ id, name, active, plans: [ { id, name, active, price } ] }]
Each plan's price is the reseller/bulk unit price (Plan.bulk_price, or your ResellerPlan override), not the retail price. For bandwidth products the plan represents GB; for IP-based products it represents IP count (read the plan name). The returned product id is the DB Product.id — that is the id you pass to /products/countries/{id}/ and use as product in order-create bodies.
curl -H "Authorization: Token <RESELLER_API_KEY>" \
https://spyderproxy.com/services/v1/reseller/products/
[
{
"id": 12,
"name": "Residential Proxies",
"active": true,
"plans": [
{ "id": 44, "name": "1 GB", "active": true, "price": 1.20 },
{ "id": 45, "name": "5 GB", "active": true, "price": 5.50 }
]
},
{
"id": 18,
"name": "Rotating Datacenter",
"active": true,
"plans": [
{ "id": 61, "name": "100 IPs", "active": true, "price": 25.00 }
]
}
]
GET/reseller/products/countries/{id}/
List the available locations/countries for a product, as reported by the upstream proxy provider.
Request
| Param | In | Type | Description |
|---|---|---|---|
id |
path | int | The DB Product.id (from /products/), not the provider ref_id. |
Response — Array of provider-defined location objects (the locations array from the matching provider product entry). Returns [] if the product exists but no provider product matches its ref_id. If the Product.id does not exist, the API returns 404.
The exact location object shape is provider-defined (residential is our residential network); the example below is representative, not guaranteed field-for-field.
curl -H "Authorization: Token <RESELLER_API_KEY>" \
https://spyderproxy.com/services/v1/reseller/products/countries/12/
[
{ "id": "US", "name": "United States" },
{ "id": "GB", "name": "United Kingdom" },
{ "id": "DE", "name": "Germany" }
]
GET/reseller/products/lte/available/
List currently available LTE (mobile 1-by-1) proxies for a given country.
Request
| Param | In | Type | Required | Description |
|---|---|---|---|---|
country |
query | str | Yes | ISO country code, e.g. US. |
Omitting country causes a 422 validation error.
Response — On provider status ok, the provider proxies array (provider-defined objects; each includes at least country_code). On any non-ok status, an empty object {} (not an array).
LTE/mobile stock comes from a separate provider (not our residential network); the upstream key is injected server-side and never exposed. The proxy object shape is provider-defined; example fields are representative.
curl -H "Authorization: Token <RESELLER_API_KEY>" \
"https://spyderproxy.com/services/v1/reseller/products/lte/available/?country=US"
[
{ "country_code": "US", "city": "New York", "carrier": "AT&T", "available": true },
{ "country_code": "US", "city": "Dallas", "carrier": "T-Mobile", "available": true }
]
GET/reseller/products/lte/countries/
List the country codes that currently have LTE proxies available (US first, then the unique non-US countries).
Request — No path params, query params, or body.
Response — Array of country-code strings, with "US" always inserted first followed by the de-duplicated set of non-US country codes that have stock. The order of the non-US codes is not deterministic (built from a set). Returns {} (empty object) if the provider status is not ok.
curl -H "Authorization: Token <RESELLER_API_KEY>" \
https://spyderproxy.com/services/v1/reseller/products/lte/countries/
["US", "CA", "GB", "DE", "FR"]
Orders
Mounted at /reseller/orders/. Orders are always scoped to your reseller account — you only ever see and act on your own orders.
OrderSchema (returned by most order endpoints):
| Field | Type | Description |
|---|---|---|
id |
int | Order id. |
product |
str | Product name. |
plan |
str | Plan name. |
subuser |
int | null | Assigned sub-user id. |
location |
str | int | null | Location. |
quantity |
int | Quantity ordered. |
total_amount |
decimal | Amount charged. |
status |
str | Human display, e.g. "Completed", "In Progress", "Pending", "Rejected". |
data |
object | Provider payload, including proxies. |
GET/reseller/orders/
List the authenticated reseller's orders (paginated), optionally filtered to one sub-user.
Request
| Param | In | Type | Default | Description |
|---|---|---|---|---|
subuser |
query | int | — | Restrict to orders whose subuser_id matches. |
limit |
query | int | 100 | Pagination page size. |
offset |
query | int | 0 | Pagination offset. |
Response — Paginated envelope {"items": [OrderSchema...], "count": int}.
curl -X GET 'https://spyderproxy.com/services/v1/reseller/orders/?subuser=42&limit=20&offset=0' \
-H 'Authorization: Token <RESELLER_API_KEY>'
{
"items": [
{
"id": 10231,
"product": "Datacenter Proxies",
"plan": "30 Days",
"subuser": 42,
"location": "US",
"quantity": 5,
"total_amount": 12.50,
"status": "Completed",
"data": {"location": "US", "proxies": [{"ip": "1.2.3.4", "port_http": 12323, "port_socks": 12324, "username": "u", "password": "p"}]}
}
],
"count": 1
}
POST/reseller/orders/lte/
Purchase a single LTE (mobile 1-by-1) proxy order.
Request — JSON body:
| Field | Type | Required | Description |
|---|---|---|---|
plan |
int | Yes | The LTE offer/proxy_id from the LTE availability listing (stored as data.plan_id). |
subuser |
int | null | No | Assign the order to one of your sub-users. |
Quantity is hard-coded to 1. The wallet is charged the plan price (ResellerPlan override else Plan.bulk_price) × 1. The subuser, if given, must belong to you or you get 404 SUBUSER_404.
Response — OrderSchema. location is always null for LTE and quantity is always 1. data carries {"plan_id": <id>} and, once provisioned, a "proxies" string "host:port:user:pass". If the provider does not return the proxy immediately, the order can come back "In Progress" — poll GET /reseller/orders/{id}/.
curl -X POST 'https://spyderproxy.com/services/v1/reseller/orders/lte/' \
-H 'Authorization: Token <RESELLER_API_KEY>' \
-H 'Content-Type: application/json' \
-d '{"plan": 88123, "subuser": 42}'
{
"id": 10240,
"product": "LTE Mobile Proxy",
"plan": "LTE",
"subuser": 42,
"location": null,
"quantity": 1,
"total_amount": 4.00,
"status": "Completed",
"data": {"plan_id": 88123, "proxies": "45.66.77.88:12000:user123:pass123"}
}
POST/reseller/orders/
Create/purchase a proxy order for a given plan (datacenter/ISP-style products).
Request — JSON body:
| Field | Type | Required | Description |
|---|---|---|---|
product |
int | Yes | DB Product.id. |
plan |
int | Yes | The DB Plan.id (not ref_id). |
location |
int | Yes | A provider location id (e.g. from GET /reseller/products/countries/{id}/). |
quantity |
int | Yes | Quantity to order. |
subuser |
int | null | No | Assign to a sub-user. |
port |
str | No | "socks5" or "http\|https". Accepted by the schema but NOT used by this handler — it has no effect. |
The plan is looked up by DB id and the product is derived from it. Product-specific rules (e.g. minimum quantity) are enforced by validate_order(). The wallet is charged reseller price × quantity; a gateway/out-of-stock failure during processing rejects the order and refunds the wallet.
Rejected product types:
- TOPUP → 400 "Can't order this product."
- MOBILE → 400 "Use LTE Purchase endpoint." (use POST /reseller/orders/lte/)
- RESIDENTIAL → 401 OUT_OF_STOCK (residential bandwidth is topped up through the dedicated residential / budget-residential / exresidential modules, not here).
Response — OrderSchema. data = {"location": <str>, "proxies": <list|null>}; proxies is populated when the provider confirms, otherwise null while status is "In Progress". Poll GET /reseller/orders/{id}/.
curl -X POST 'https://spyderproxy.com/services/v1/reseller/orders/' \
-H 'Authorization: Token <RESELLER_API_KEY>' \
-H 'Content-Type: application/json' \
-d '{"product": 3, "plan": 17, "location": 12, "quantity": 5, "subuser": 42, "port": "http|https"}'
{
"id": 10251,
"product": "Datacenter Proxies",
"plan": "30 Days",
"subuser": 42,
"location": "12",
"quantity": 5,
"total_amount": 12.50,
"status": "In Progress",
"data": {"location": "US", "proxies": null}
}
GET/reseller/orders/{id}/
Fetch one order's details; refreshes the proxy list from the provider if the order is still provisioning.
Request
| Param | In | Type | Description |
|---|---|---|---|
id |
path | int | The ResellerOrder id. |
Only returns orders you own; otherwise 404 ORDER_404. If the status is IN_PROGRESS it calls the provider live: for MOBILE it re-pulls the latest LTE proxy; for other products it reads the provider order and, once confirmed, fills data.proxies (http port 12323, socks port 12324) and flips the status to "Completed". This is the polling endpoint after an order comes back "In Progress".
Response — OrderSchema for the order.
curl -X GET 'https://spyderproxy.com/services/v1/reseller/orders/10251/' \
-H 'Authorization: Token <RESELLER_API_KEY>'
{
"id": 10251,
"product": "Datacenter Proxies",
"plan": "30 Days",
"subuser": 42,
"location": "US",
"quantity": 5,
"total_amount": 12.50,
"status": "Completed",
"data": {"location": "US", "proxies": [{"ip": "1.2.3.4", "port_http": 12323, "port_socks": 12324, "username": "u", "password": "p"}]}
}
POST/reseller/orders/{id}/extend/
Extend/renew an existing completed, time-based order for another plan period.
Request
| Param | In | Type | Default | Description |
|---|---|---|---|---|
id |
path | int | — | The order id. |
plan_id |
body | int | null | null | Omit (or send null) to renew on the order's existing plan; supply it to renew onto a different duration of the same product. If given, it must belong to the same product and be active. |
The JSON body is optional.
Preconditions (each a 400 GENERIC_ERROR unless noted):
- Order must be COMPLETED — "Only completed orders can be extended."
- Order must have a provider ref_id — "...cannot be extended."
- Product must be time-extendable — not one of TOPUP, RESIDENTIAL, PREMIUM_RESIDENTIAL, BUDGET_RESIDENTIAL, MOBILE, ROTATING_MOBILE, ROTATING_DATACENTER (bandwidth-pool products — buy more GB instead).
Pricing mirrors order creation: ResellerPlan override else Plan.bulk_price, × order.quantity; 402 INSUFFICIENT_BALANCE if the wallet is too low. The wallet is debited before the provider extend call; on any provider exception the wallet is refunded and 400 GATEWAY_FAIL is raised (the order is left untouched). On success, expired_at = max(current expiry, now) + plan.duration and the renewal is appended to data.extends[].
Response — OrderSchema for the extended order.
curl -X POST 'https://spyderproxy.com/services/v1/reseller/orders/10251/extend/' \
-H 'Authorization: Token <RESELLER_API_KEY>' \
-H 'Content-Type: application/json' \
-d '{"plan_id": 18}'
{
"id": 10251,
"product": "Datacenter Proxies",
"plan": "30 Days",
"subuser": 42,
"location": "US",
"quantity": 5,
"total_amount": 12.50,
"status": "Completed",
"data": {"location": "US", "proxies": [{"ip": "1.2.3.4", "port_http": 12323, "port_socks": 12324, "username": "u", "password": "p"}], "extends": [{"date": "2026-08-21T10:00:00+00:00", "price": "12.50", "plan": "30 Days", "plan_id": 18}]}
}
Residential
Mounted at /reseller/residential/. This is the current residential network (host resi.spyderproxy.com). Bandwidth quantities are in GB.
POST/reseller/residential/{id}/traffic/give/
Allocate residential bandwidth (GB) to a sub-user from your residential pool, charging your wallet. Auto-creates the residential sub-user on first top-up.
Request
| Param | In | Type | Description |
|---|---|---|---|
id |
path | int | Your own Subuser.id. |
quantity |
body | int | Amount of residential bandwidth to add, in GB. |
Internally converted to bytes as quantity × 1024³. Price = quantity × (ResellerPlan price if set, else plan.bulk_price) for the residential product's first plan; the wallet is checked and debited inside a DB transaction and a ResellerOrder (expiring in 90 days) is recorded COMPLETED (or REJECTED on failure). If the sub-user has no residential account yet, one is created (a proxy_type residential identity) and the returned credentials are saved back onto the sub-user. No explicit minimum quantity beyond the integer type.
Response — 200 {"success": true}.
curl -X POST 'https://spyderproxy.com/services/v1/reseller/residential/42/traffic/give/' \
-H 'Authorization: Token <RESELLER_API_KEY>' \
-H 'Content-Type: application/json' \
-d '{"quantity": 5}'
{"success": true}
POST/reseller/residential/{id}/traffic/take/
Reclaim residential bandwidth (GB) from a sub-user and credit it back to your wallet.
Request
| Param | In | Type | Description |
|---|---|---|---|
id |
path | int | Your Subuser.id. |
quantity |
body | int | Amount of residential bandwidth to pull back, in GB. |
Gotcha: unlike
/traffic/give/(which uses our residential network), the take path reads availability and performs the reclaim through the legacy residential gateway (get_subuserfortraffic_available, thentake_traffic). Available bandwidth must be>=quantity or you get403 INSUFFICIENT_BANDWIDTH. The wallet is creditedquantity × (ResellerPlan price if set, else plan.bulk_price)inside a DB transaction. NoResellerOrderrow is created for a take.
Errors — 404 SUBUSER_404; 400 SUBUSER_400 "This subuser cant be used for this request" when the sub-user has no provider account (no sub_id); 403 INSUFFICIENT_BANDWIDTH "Insufficient Residential Bandwidth.".
Response — 200 {"success": true}.
curl -X POST 'https://spyderproxy.com/services/v1/reseller/residential/42/traffic/take/' \
-H 'Authorization: Token <RESELLER_API_KEY>' \
-H 'Content-Type: application/json' \
-d '{"quantity": 2}'
{"success": true}
POST/reseller/residential/generate/
Generate ready-to-use residential proxy connection strings for a sub-user. residential sub-users are built client-side; legacy sub-users go through the old residential gateway.
Request — JSON body (GenerateSchema):
| Field | Type | Required | Description |
|---|---|---|---|
format |
str | Yes | One of the four literal templates: "{hostname}:{port}:{username}:{password}", "{hostname}:{port}@{username}:{password}", "{username}:{password}:{hostname}:{port}", "{username}:{password}@{hostname}:{port}". |
port |
str | Yes | "socks5" or "http\|https". |
subuser |
int | Yes | Your Subuser.id. |
country |
str | No | Country target (default null). |
location |
str | No | Legacy location string (ignored for our residential network). |
region |
str | No | Region/state target, e.g. california (our residential network; from /regions/). |
city |
str | No | City target, e.g. los+angeles (our residential network; from /cities/). |
isp |
str | No | ISP target, e.g. comcast (our residential network; from /isps/). |
lifetime |
str | No | Default null. |
rotation |
str | Yes | "random" or "sticky". |
quantity |
int | Yes | Number of proxy lines to generate. |
Routing is by subuser.provider:
- residential sub-users — proxies are built locally from the sub-user's stored credentials, no upstream call. Host/port are fixed to resi.spyderproxy.com:5000. rotation is normalized to "random" or "sticky" (anything not exactly "random" ⇒ sticky). Sticky lines append a per-line session id (-sid-<12 hex>) so each line is a distinct sticky session; random lines omit it (rotating IP per request). Geo targeting is encoded into the username: country (a 2-letter code is upper-cased, e.g. -country-US; a country name is resolved to its code), plus optional region, city, and isp — each appended as -region-…, -city-…, -isp-… with values lowercased and spaces turned into + (exactly the form returned by the lookup endpoints below). The location and lifetime fields are ignored on this route; format selects the output template. Discover valid values by cascading the lookups: country → region → city/ISP.
- Legacy (non-our residential network, non-the premium residential network) sub-users — location = location or country and must contain an underscore (e.g. country_region) or you get 400 GENERIC_ERROR "Please format the location field properly". Proxies are fetched via the legacy residential gateway and the host the legacy proxy host is rewritten to the configured proxy address.
- premium residential sub-users — rejected with 400 SUBUSER_400.
Response — 200: JSON array of proxy strings (List[str]) in the chosen format. Errors: 404 SUBUSER_404; 400 SUBUSER_400 (the premium residential network); 400 GENERIC_ERROR (legacy location formatting).
curl -X POST 'https://spyderproxy.com/services/v1/reseller/residential/generate/' \
-H 'Authorization: Token <RESELLER_API_KEY>' \
-H 'Content-Type: application/json' \
-d '{
"format": "{username}:{password}@{hostname}:{port}",
"port": "http|https",
"subuser": 42,
"country": "US",
"region": "california",
"city": "los+angeles",
"isp": "comcast",
"rotation": "sticky",
"quantity": 3
}'
[
"resiUser-country-US-region-california-city-los+angeles-isp-comcast-sid-a1b2c3d4e5f6:[email protected]:5000",
"resiUser-country-US-region-california-city-los+angeles-isp-comcast-sid-f6e5d4c3b2a1:[email protected]:5000"
]
GET/reseller/residential/countries/
List the residential target countries available on our residential network.
Request — No path or query params, no body.
Response — 200: verbatim passthrough of our residential network /countries?connection_type=residential response. Use the returned country_code values as the country field on /reseller/residential/generate/ (the 2-letter code is emitted verbatim, upper-cased, into the proxy username). The exact JSON shape is whatever our residential network returns; the example below is representative. For finer targeting, use the /regions/, /cities/, and /isps/ endpoints below to discover valid region, city, and isp values to pass to /generate/.
curl -X GET 'https://spyderproxy.com/services/v1/reseller/residential/countries/' \
-H 'Authorization: Token <RESELLER_API_KEY>'
{
"data": [
{"country_code": "US", "country": "United States"},
{"country_code": "GB", "country": "United Kingdom"},
{"country_code": "DE", "country": "Germany"}
]
}
GET/reseller/residential/regions/
List our residential network regions/states available for a country (residential targeting).
Request
| Param | In | Type | Required | Description |
|---|---|---|---|---|
country |
query | str | Yes | 2-letter country code (or country name) — resolved to a our residential network country code. |
Response — 200: {"regions": ["alabama", "california", "new+jersey", …]}. Pass a value verbatim as the region field on /generate/.
curl -X GET 'https://spyderproxy.com/services/v1/reseller/residential/regions/?country=US' \
-H 'Authorization: Token <RESELLER_API_KEY>'
{"regions": ["alabama", "alaska", "arizona", "arkansas", "california", "colorado", "florida"]}
GET/reseller/residential/cities/
List our residential network cities for a country, optionally narrowed by region.
Request
| Param | In | Type | Required | Description |
|---|---|---|---|---|
country |
query | str | Yes | Country code or name. |
region |
query | str | No | Region/state to narrow the list, e.g. california. |
Response — 200: {"cities": ["acton", "los+angeles", "san+diego", …]}. Pass a value verbatim as the city field on /generate/.
curl -X GET 'https://spyderproxy.com/services/v1/reseller/residential/cities/?country=US®ion=california' \
-H 'Authorization: Token <RESELLER_API_KEY>'
{"cities": ["acton", "alameda", "alhambra", "los+angeles", "san+diego", "san+francisco"]}
GET/reseller/residential/isps/
List our residential network ISPs for a country, optionally narrowed by region and/or city.
Request
| Param | In | Type | Required | Description |
|---|---|---|---|---|
country |
query | str | Yes | Country code or name. |
region |
query | str | No | Region/state to narrow the list. |
city |
query | str | No | City to narrow the list. |
Response — 200: {"isps": ["at&t+internet", "comcast", "verizon", …]}. Pass a value verbatim as the isp field on /generate/.
curl -X GET 'https://spyderproxy.com/services/v1/reseller/residential/isps/?country=US®ion=california' \
-H 'Authorization: Token <RESELLER_API_KEY>'
{"isps": ["at&t+internet", "astound+broadband", "comcast", "spectrum", "verizon"]}
Budget Residential
Mounted at /reseller/budget-residential/. Provider: the budget residential network. Router-level auth applies to every endpoint. Bandwidth quantities are in GB at the API surface (converted to MB internally, since the budget residential network uses MB while our residential network-backed residential uses bytes).
POST/reseller/budget-residential/{id}/traffic/give/
Add bandwidth to an existing the budget residential network budget-residential sub-user, charging your wallet.
Request
| Param | In | Type | Description |
|---|---|---|---|
id |
path | int | The Subuser.id (must belong to you; 404 SUBUSER_404 otherwise). |
quantity |
body | int | Bandwidth to add, in GB (converted to MB as quantity × 1024 and added to the sub-user's the budget residential network traffic_limit). |
The charge + top-up run in a DB transaction with the reseller's user row locked. Price = ResellerPlan.price if set, else plan.bulk_price, × quantity. A ResellerOrder is created (budget product/first plan, expired_at = now + 730 days — a 2-year expiry): COMPLETED on success (wallet debited), REJECTED on failure (error re-raised). 402 INSUFFICIENT_BALANCE if the wallet is too low.
Response — 200 {"success": true}.
curl -X POST 'https://spyderproxy.com/services/v1/reseller/budget-residential/812/traffic/give/' \
-H 'Authorization: Token <RESELLER_API_KEY>' \
-H 'Content-Type: application/json' \
-d '{"quantity": 10}'
{
"success": true
}
POST/reseller/budget-residential/generate/
Generate rotating/sticky the budget residential network budget-residential proxy connection strings for a sub-user.
Request — JSON body (GenerateSchema):
| Field | Type | Required | Description |
|---|---|---|---|
format |
str | Yes | One of the four literal templates (see Residential /generate/). |
port |
str | Yes | "socks5" or "http\|https". |
subuser |
int | Yes | The Subuser.id — must be a the budget residential network/budget-provider sub-user owned by you. |
country |
str | No | Geo target (default null). |
location |
str | No | Geo target (default null). |
lifetime |
str | No | Sticky-session lifetime (default null). |
rotation |
str | Yes | "random" or "sticky". |
quantity |
int | Yes | Number of proxy lines to generate. |
This endpoint only formats existing credentials into proxy lines — it does not add bandwidth or charge the wallet (use /traffic/give/ to top up). If the sub-user is not a the budget residential network/budget sub-user owned by you, it raises 404 SUBUSER_404.
Response — 200: a list of proxy connection strings, one per requested quantity, each in the chosen format. The exact strings are produced by the the budget residential network gateway; the example values below are illustrative.
curl -X POST 'https://spyderproxy.com/services/v1/reseller/budget-residential/generate/' \
-H 'Authorization: Token <RESELLER_API_KEY>' \
-H 'Content-Type: application/json' \
-d '{
"format": "{hostname}:{port}:{username}:{password}",
"port": "http|https",
"subuser": 812,
"country": "US",
"rotation": "sticky",
"quantity": 3
}'
[
"geo.spyderproxy.com:9000:budgetuser812:pass_abc123",
"geo.spyderproxy.com:9001:budgetuser812:pass_abc123",
"geo.spyderproxy.com:9002:budgetuser812:pass_abc123"
]
GET/reseller/budget-residential/countries/
List the countries/locations available for the budget residential network budget-residential proxies.
Request — No path params, query params, or body.
Response — 200: read-only passthrough of the the budget residential network locations list, used for the country/location fields of /generate/. The exact object shape is produced by the the budget residential network gateway; fields shown are illustrative.
curl -X GET 'https://spyderproxy.com/services/v1/reseller/budget-residential/countries/' \
-H 'Authorization: Token <RESELLER_API_KEY>'
[
{"code": "US", "name": "United States"},
{"code": "GB", "name": "United Kingdom"},
{"code": "DE", "name": "Germany"}
]
Legacy Residential
Mounted at /reseller/old-residential/. This is the deprecated legacy residential module. Every route still requires a valid, active reseller token (401 otherwise).
Gotcha: despite the module name (\"old residential / legacy the legacy residential network\"), the generate and countries handlers use the the premium residential network gateway, not the legacy residential network.
POST/reseller/old-residential/{id}/traffic/give/
Allocate/top-up residential traffic (GB) to an existing reseller order — DISABLED, always returns 400.
Request
| Param | In | Type | Description |
|---|---|---|---|
id |
path | int | The ResellerOrder id (ignored). |
quantity |
body | int | Traffic in GB (ignored). |
The handler unconditionally raises 400 before any of the body/path is used, so the success path is unreachable and old-residential traffic top-ups can no longer be purchased.
Response — Always HTTP 400 with {"detail": "Can't purchase old residential!"}.
curl -X POST "https://spyderproxy.com/services/v1/reseller/old-residential/123/traffic/give/" \
-H "Authorization: Token <RESELLER_API_KEY>" \
-H "Content-Type: application/json" \
-d '{"quantity": 5}'
{
"detail": "Can't purchase old residential!"
}
POST/reseller/old-residential/generate/
Generate residential proxy connection strings for one of your sub-users (via the the premium residential network gateway).
Request — JSON body (GenerateSchema):
| Field | Type | Required | Description |
|---|---|---|---|
format |
str | Yes | One of the four literal templates (see Residential /generate/). |
port |
str | Yes | "socks5" or "http\|https". |
subuser |
int | Yes | Subuser.id, must belong to you. |
country |
str | No | Default null. |
location |
str | No | Default null. |
lifetime |
str | No | Default null. |
rotation |
str | Yes | "random" or "sticky". |
quantity |
int | Yes | Number of proxy lines to generate. |
Uses the sub-user's own username/password. If no matching sub-user exists for you, raises 404 SUBUSER_404. This is a generation-only endpoint — it does not consume or charge bandwidth.
Response — Passthrough of the the premium residential network gateway's raw output: a list of proxy connection strings in the requested format. Element shape is provider-defined.
curl -X POST "https://spyderproxy.com/services/v1/reseller/old-residential/generate/" \
-H "Authorization: Token <RESELLER_API_KEY>" \
-H "Content-Type: application/json" \
-d '{
"format": "{hostname}:{port}:{username}:{password}",
"port": "http|https",
"subuser": 42,
"country": "us",
"rotation": "sticky",
"quantity": 3
}'
[
"gateway.example.net:8080:subuser42:s3cr3t",
"gateway.example.net:8080:subuser42:s3cr3t",
"gateway.example.net:8080:subuser42:s3cr3t"
]
GET/reseller/old-residential/countries/
List available residential proxy locations/countries (via the the premium residential network gateway).
Request — No path params, query params, or body.
Response — Passthrough of the the premium residential network gateway's raw locations list; the codes feed the country/location params of POST /generate/. Element shape is provider-defined.
curl -X GET "https://spyderproxy.com/services/v1/reseller/old-residential/countries/" \
-H "Authorization: Token <RESELLER_API_KEY>"
[
{"code": "us", "name": "United States"},
{"code": "gb", "name": "United Kingdom"},
{"code": "de", "name": "Germany"}
]
ExResidential
Mounted at /reseller/exresidential/. An extended residential tier. This module currently exposes a single route. Bandwidth is in GB at the API surface.
POST/reseller/exresidential/{id}/traffic/give/
Allocate (give) bandwidth to an existing ExResidential (our residential network) sub-user.
Request
| Param | In | Type | Description |
|---|---|---|---|
id |
path | int | The target Subuser.id (must belong to you; it is a sub-user id, not an order id). |
quantity |
body | int | Amount of bandwidth to allocate, in GB (whole GB). |
The service resolves the sub-user scoped to your reseller account and raises SUBUSER_404 if it is not yours. Insufficient wallet balance raises INSUFFICIENT_BALANCE; an upstream our residential network rejection surfaces as a gateway failure ({"code": int, "message": str}).
Response — The raw result of the service call (untyped — no response schema is declared, so field names come from the service layer). The example fields below are illustrative.
curl -X POST 'https://spyderproxy.com/services/v1/reseller/exresidential/512/traffic/give/' \
-H 'Authorization: Token <RESELLER_API_KEY>' \
-H 'Content-Type: application/json' \
-d '{"quantity": 5}'
{
"success": true,
"subuser": 512,
"quantity": 5
}
Subusers
Mounted at /reseller/subusers/. Sub-users are your end-customers. All queries are scoped to your reseller account — you only ever see your own sub-users.
GET/reseller/subusers/
List all sub-users belonging to the authenticated reseller (paginated).
Request
| Param | In | Type | Default | Description |
|---|---|---|---|---|
limit |
query | int | 100 | Pagination page size. |
offset |
query | int | 0 | Pagination offset. |
Response — Pagination envelope { items: [SubuserSchema], count: int }. SubuserSchema fields: id (int), username (str | null), password (str | null), created_at (datetime ISO-8601).
This endpoint does not return bandwidth/GB usage, and
username/passwordmay benullfor placeholder residential sub-users created withgb=0. UseGET /reseller/subusers/{id}/for live usage.
curl 'https://spyderproxy.com/services/v1/reseller/subusers/?limit=50&offset=0' \
-H 'Authorization: Token <RESELLER_API_KEY>'
{
"items": [
{
"id": 87,
"username": "pe_user_x9f2",
"password": "pe_pass_abcd12",
"created_at": "2026-08-21T14:32:00Z"
},
{
"id": 42,
"username": null,
"password": null,
"created_at": "2026-08-10T09:15:00Z"
}
],
"count": 2
}
GET/reseller/subusers/{id}/
Retrieve one sub-user with live used/unused bandwidth (GB) fetched from its upstream provider.
Request
| Param | In | Type | Description |
|---|---|---|---|
id |
path | int | The Subuser.id, must belong to you. |
Response — SubuserDetails: id (int), username (str | null), password (str | null), created_at (datetime), unused_gb (float), used_gb (float). Returns 404 {"detail": "Subuser does not exist."} if not found or not owned by you.
used_gb/unused_gbare live-queried from the sub-user's provider gateway. If the sub-user has no upstreamsub_id(e.g. a placeholder created withgb=0), both are0with no gateway call. Traffic is read live from whichever residential network the sub-user is provisioned on. A provider outage on the traffic lookup can surface as an error on this call.
curl 'https://spyderproxy.com/services/v1/reseller/subusers/87/' \
-H 'Authorization: Token <RESELLER_API_KEY>'
{
"id": 87,
"username": "pe_user_x9f2",
"password": "pe_pass_abcd12",
"created_at": "2026-08-21T14:32:00Z",
"unused_gb": 4.53,
"used_gb": 0.47
}
POST/reseller/subusers/
Create a new sub-user. The type selects the provider.
Request — JSON body (SubuserCreateSchema):
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
email |
str | Yes | — | Required for all types; only meaningfully used for budget (the budget residential network) and to key placeholder/budget records. Residential auto-generates its own provider email. |
gb |
int | No | 0 | Meaning depends on type (see below). |
type |
enum | No | "residential" |
One of "residential", "exresidential", "budget". |
Behavior by type:
- residential — if gb > 0, provisions bandwidth on our residential network (gb × 1024³ bytes) with an auto-generated email resi-<hex>@sub.spyderproxy.io, sets the residential provider, and charges the wallet. If gb = 0, creates a bare placeholder record (no provider call; provider defaults to the legacy residential network; username/password null).
- exresidential — gb is treated as a quantity of premium residential units (must be > 0); provisions the extended residential units, creates a COMPLETED ResellerOrder with a 90-day expiry, and charges the wallet.
- budget — gb is ignored; creates a the budget residential network (provider=budget) sub-user with 0 traffic using email.
Pricing uses your ResellerPlan price when set, otherwise plan.bulk_price.
Response — SubuserSchema: id, username, password, created_at. username/password carry the provider proxy credentials for provisioned sub-users; both are null for a residential placeholder (gb=0).
Errors — 400 GATEWAY_FAIL "Gateway failed to process your request, try later." if the provider returns no id/credentials; 402 INSUFFICIENT_BALANCE "Insufficient Balance." if the wallet cannot cover the charge (residential gb>0 and exresidential both pre-check and debit); 400 GENERIC_ERROR for exresidential when gb <= 0.
curl -X POST 'https://spyderproxy.com/services/v1/reseller/subusers/' \
-H 'Authorization: Token <RESELLER_API_KEY>' \
-H 'Content-Type: application/json' \
-d '{"email":"[email protected]","gb":5,"type":"residential"}'
{
"id": 88,
"username": "pe_user_k3d9",
"password": "pe_pass_ffa210",
"created_at": "2026-08-21T15:04:11Z"
}
Rotating Mobile
Mounted at /reseller/rotating-mobile/. Provider: Fleet mobile gateway. Location/ISP catalog responses are returned verbatim from the provider; example shapes are illustrative.
GET/reseller/rotating-mobile/details/
Get a sub-user's rotating-mobile account credentials and traffic usage.
Request
| Param | In | Type | Required | Description |
|---|---|---|---|---|
subuser |
query | int | Yes | The Subuser.id owned by you. |
Response — { username, password, available_traffic, used_traffic }. Traffic values pass through unchanged from the Fleet gateway.
404 SUBUSER_404if not found/owned;400 SUBUSER_400 "This subuser has no active rotating mobile account."whensub_idis empty;400 SUBUSER_400 "An error has occured, please try again later."when the gateway returns no data or omitsusername.
curl -X GET 'https://spyderproxy.com/services/v1/reseller/rotating-mobile/details/?subuser=42' \
-H 'Authorization: Token <RESELLER_API_KEY>'
{
"username": "mob_a1b2c3",
"password": "s3cretPass",
"available_traffic": 5.0,
"used_traffic": 1.23
}
GET/reseller/rotating-mobile/countries/
List all countries available for rotating-mobile proxies.
Request — No path params, query params, or body.
Response — Passthrough of the Fleet gateway's mobile country list.
curl -X GET 'https://spyderproxy.com/services/v1/reseller/rotating-mobile/countries/' \
-H 'Authorization: Token <RESELLER_API_KEY>'
[
{"code": "US", "name": "United States"},
{"code": "GB", "name": "United Kingdom"}
]
GET/reseller/rotating-mobile/regions/{country}/
List regions/states within a country for rotating-mobile targeting.
Request
| Param | In | Type | Required | Description |
|---|---|---|---|---|
country |
path | str | Yes | Country code/identifier. |
Response — Passthrough of the Fleet gateway's region list.
curl -X GET 'https://spyderproxy.com/services/v1/reseller/rotating-mobile/regions/US/' \
-H 'Authorization: Token <RESELLER_API_KEY>'
[
{"code": "CA", "name": "California"},
{"code": "NY", "name": "New York"}
]
GET/reseller/rotating-mobile/cities/{country}/
List cities within a country (optionally scoped to a region) for rotating-mobile targeting.
Request
| Param | In | Type | Required | Default | Description |
|---|---|---|---|---|---|
country |
path | str | Yes | — | Country code/identifier. |
region |
query | str | No | null | Narrow to one region; omit to list cities across the whole country. |
Response — Passthrough of the Fleet gateway's city list.
curl -X GET 'https://spyderproxy.com/services/v1/reseller/rotating-mobile/cities/US/?region=CA' \
-H 'Authorization: Token <RESELLER_API_KEY>'
[
{"name": "Los Angeles"},
{"name": "San Francisco"}
]
GET/reseller/rotating-mobile/isps/{country}/
List mobile carriers/ISPs available in a country (optionally scoped to region and city).
Request
| Param | In | Type | Required | Default | Description |
|---|---|---|---|---|---|
country |
path | str | Yes | — | Country code/identifier. |
region |
query | str | No | null | Narrow the ISP list to a region. |
city |
query | str | No | null | Narrow the ISP list to a city. |
Response — Passthrough of the Fleet gateway's ISP/carrier list.
curl -X GET 'https://spyderproxy.com/services/v1/reseller/rotating-mobile/isps/US/?region=CA&city=Los%20Angeles' \
-H 'Authorization: Token <RESELLER_API_KEY>'
[
{"name": "AT&T"},
{"name": "Verizon"},
{"name": "T-Mobile"}
]
POST/reseller/rotating-mobile/generate/
Generate rotating-mobile proxy connection strings for a sub-user with geo/rotation targeting.
Request — JSON body (RotatingMobileGenerateSchema):
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
subuser |
int | Yes | — | Subuser.id. |
count |
int | No | 10 | Number of proxies to generate. |
country_id |
str | No | null | Forwarded to the generator's country argument. |
region |
str | No | null | Region target. |
city |
str | No | null | City target. |
isp |
str | No | null | ISP/carrier target. |
ttl |
int | No | null | Sticky-session time-to-live (used when rotation="sticky"). |
rotation |
enum | No | "random" |
"random" or "sticky". |
proxy_format |
int | No | 0 | Index selecting the output proxy string format. |
Generation does not charge or allocate — it only builds proxy strings for an existing mobile sub-user (use /purchase/ to buy quantity). If the sub-user is not found/owned, raises 404 SUBUSER_404.
Response — { proxies: [...], subuser_details: {...} }. proxies is a list of generated proxy strings (layout determined by proxy_format); subuser_details is the Fleet gateway account info. Example is illustrative.
curl -X POST 'https://spyderproxy.com/services/v1/reseller/rotating-mobile/generate/' \
-H 'Authorization: Token <RESELLER_API_KEY>' \
-H 'Content-Type: application/json' \
-d '{
"subuser": 42,
"count": 5,
"country_id": "US",
"region": "CA",
"city": "Los Angeles",
"isp": "AT&T",
"ttl": 600,
"rotation": "sticky",
"proxy_format": 0
}'
{
"proxies": [
"mob_a1b2c3:[email protected]:8000",
"mob_a1b2c3:[email protected]:8001"
],
"subuser_details": {
"username": "mob_a1b2c3",
"password": "s3cretPass",
"available_traffic": 5.0,
"used_traffic": 1.23
}
}
POST/reseller/rotating-mobile/purchase/
Purchase rotating-mobile traffic/quantity, optionally assigned to a sub-user and with a coupon.
Request — JSON body (ResellerRotatingMobilePurchaseSchema):
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
quantity |
int | Yes | — | Amount to purchase. |
subuser |
int | No | null | Subuser.id to assign the purchase to. |
coupon |
str | No | null | Coupon code. |
product |
int | No | — | Present on the schema but NOT used by this route. |
plan |
int | No | — | Present on the schema but NOT used by this route. |
Only quantity, subuser, and coupon are read. Charging debits your wallet via the order flow; insufficient balance raises INSUFFICIENT_BALANCE.
Response — The order/result object from the reseller-orders service (shape defined there; the example is illustrative).
curl -X POST 'https://spyderproxy.com/services/v1/reseller/rotating-mobile/purchase/' \
-H 'Authorization: Token <RESELLER_API_KEY>' \
-H 'Content-Type: application/json' \
-d '{
"quantity": 2,
"subuser": 42,
"coupon": "SAVE10"
}'
{
"id": 1001,
"subuser": 42,
"quantity": 2,
"total_amount": "18.00",
"status": "completed"
}
Rotating Datacenter
Mounted at /reseller/rotating-datacenter/. Provider: Fleet gateway. Traffic figures are reported in the Fleet account's native units (GB).
GET/reseller/rotating-datacenter/details/
Get the rotating datacenter sub-user's Fleet credentials and traffic usage.
Request
| Param | In | Type | Required | Description |
|---|---|---|---|---|
subuser |
query | int | Yes | The Subuser.id owned by you; must already have a provisioned datacenter account (non-empty sub_id). |
Response — { username, password, available_traffic, used_traffic }, pulled live from the Fleet account.
Errors:
404 SUBUSER_404 "Subuser was not found";400 SUBUSER_400 "This subuser has no active rotating datacenter account."if there is nosub_id;400 SUBUSER_400 "An error has occured, please try again later."if the Fleet lookup returns nothing / no username.
curl -X GET "https://spyderproxy.com/services/v1/reseller/rotating-datacenter/details/?subuser=118" \
-H "Authorization: Token <RESELLER_API_KEY>"
{
"username": "fleet_dc_84213",
"password": "Xq9v2Lm7Ptz",
"available_traffic": 42.5,
"used_traffic": 7.5
}
GET/reseller/rotating-datacenter/countries/
List the datacenter countries available for proxy generation.
Request — No path params, query params, or body.
Response — JSON array of datacenter country entries from the Fleet gateway. Each entry carries a country identifier/code (usable as country_id in /generate/) and a display name. Field names are provider-defined; the example is illustrative.
curl -X GET "https://spyderproxy.com/services/v1/reseller/rotating-datacenter/countries/" \
-H "Authorization: Token <RESELLER_API_KEY>"
[
{"id": "us", "name": "United States"},
{"id": "de", "name": "Germany"},
{"id": "gb", "name": "United Kingdom"}
]
POST/reseller/rotating-datacenter/generate/
Generate rotating datacenter proxy connection strings for an existing sub-user and return its account details.
Request — JSON body (RotatingDatacenterGenerateSchema):
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
subuser |
int | Yes | — | Subuser.id owned by you. |
count |
int | No | 10 | Number of proxy strings to generate. |
country_id |
str | null | No | null | Country code from /countries/ (null = default/any). |
rotation |
enum | No | "random" |
"random" or "sticky". |
proxy_format |
int | No | 0 | Index into the provider's format templates (0 = default). |
This endpoint does not buy anything and does not consume balance — it only builds proxy strings for a sub-user that already has a datacenter account and echoes back its usage. Internally uses the sub-user's Fleet username/password (not the DB id). Error: 404 SUBUSER_404 "Subuser was not found" if the sub-user isn't owned by you.
Response — { proxies: [...], subuser_details: {...} }. proxies layout is determined by proxy_format (the example strings are illustrative); subuser_details matches GET /details/.
curl -X POST "https://spyderproxy.com/services/v1/reseller/rotating-datacenter/generate/" \
-H "Authorization: Token <RESELLER_API_KEY>" \
-H "Content-Type: application/json" \
-d '{"subuser": 118, "count": 10, "country_id": "us", "rotation": "sticky", "proxy_format": 0}'
{
"proxies": [
"dc.spyderproxy.io:12323:fleet_dc_84213:Xq9v2Lm7Ptz",
"dc.spyderproxy.io:12323:fleet_dc_84213:Xq9v2Lm7Ptz"
],
"subuser_details": {
"username": "fleet_dc_84213",
"password": "Xq9v2Lm7Ptz",
"available_traffic": 42.5,
"used_traffic": 7.5
}
}
POST/reseller/rotating-datacenter/buy/
Purchase or top up rotating datacenter traffic, provisioning a Fleet sub-user and charging your wallet.
Request — JSON body (ResellerRotatingDatacenterPurchaseSchema):
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
product |
int | Yes | — | Effectively ignored server-side — the rotating-datacenter product is always resolved internally. |
plan |
int | Yes | — | Plan id (resolved by id, then by ref_id) — this is what selects pricing. |
quantity |
int | Yes | — | Number of plan units to buy. Passed to the gateway as-is with no GB/byte conversion — it represents plan units. |
subuser |
int | null | No | null | Existing Subuser.id to top up; null creates a new sub-user. |
coupon |
str | null | No | null | Coupon code; unknown/invalid codes are silently ignored (no discount, no error). |
Pricing = ResellerPlan.price if you have one for the plan, else Plan.bulk_price, × quantity, minus any valid coupon discount. If subuser is supplied and already has a Fleet sub_id, traffic is added to that account; otherwise a brand-new sub-user (provider = Fleet) plus a new Fleet datacenter account is created. The whole charge + provision runs in a DB transaction; on any failure the order is marked REJECTED and the charge is rolled back.
Errors — 400 GENERIC_ERROR "Plan not found!" (plan id/ref_id doesn't match the datacenter product); 400 GENERIC_ERROR "Can't purchase bandwidth right now!" (plan inactive); 402 INSUFFICIENT_BALANCE "Insufficient Balance." (wallet < total after discount); 400 GATEWAY_FAIL if Fleet doesn't return an account id.
Response — {"success": true} on completion. No credentials are returned here — retrieve them afterward via GET /details/ or POST /generate/.
curl -X POST "https://spyderproxy.com/services/v1/reseller/rotating-datacenter/buy/" \
-H "Authorization: Token <RESELLER_API_KEY>" \
-H "Content-Type: application/json" \
-d '{"product": 12, "plan": 34, "quantity": 5, "subuser": 118, "coupon": "SAVE10"}'
{
"success": true
}
Errors
Errors are returned with an HTTP status and a JSON body carrying either a detail or a message field. Authentication failures short-circuit before the handler runs.
| HTTP | Code / condition | Message | Notes |
|---|---|---|---|
401 |
Auth failure | — | Missing, invalid, or inactive reseller token. Applies to every endpoint. |
401 |
OUT_OF_STOCK |
— | Attempting to order a RESIDENTIAL product via POST /reseller/orders/ — top up via the residential/budget-residential/exresidential modules instead. |
402 |
INSUFFICIENT_BALANCE |
Insufficient Balance. |
Wallet balance is lower than the total charge. |
403 |
INSUFFICIENT_BANDWIDTH |
Insufficient Residential Bandwidth. |
On residential/{id}/traffic/take/ when quantity exceeds the sub-user's available traffic. |
404 |
SUBUSER_404 |
Subuser was not found / Subuser does not exist. |
Sub-user id not found or not owned by the reseller. |
404 |
ORDER_404 |
— | Order id does not belong to this reseller. |
404 |
Product not found | — | GET /products/countries/{id}/ when the Product.id does not exist. |
400 |
SUBUSER_400 |
This subuser cant be used for this request / This subuser has no active rotating mobile account. / This subuser has no active rotating datacenter account. / An error has occured, please try again later. |
Sub-user has no provider account, no sub_id, is a the premium residential network sub-user on our residential network generate route, or the upstream returned no usable data. |
400 |
GATEWAY_FAIL |
Gateway failed to process your request, try later. |
Upstream provider rejected the request or returned no id/credentials. On order extend, the wallet is refunded first. |
400 |
GENERIC_ERROR |
e.g. Please format the location field properly / Only completed orders can be extended. / ...cannot be extended. / Plan not found! / Can't purchase bandwidth right now! |
Validation and precondition failures. Also covers exresidential sub-user creation with gb <= 0. |
400 |
Order product rejected | Can't order this product. (TOPUP) / Use LTE Purchase endpoint. (MOBILE) |
From POST /reseller/orders/. |
400 |
Old residential disabled | Can't purchase old residential! |
POST /reseller/old-residential/{id}/traffic/give/ always returns this. |
422 |
Validation error | — | Missing required query params (e.g. country on /products/lte/available/) or malformed request bodies. |
Provider-status-related non-errors: /products/lte/available/ and /products/lte/countries/ return an empty object {} (HTTP 200) when the upstream LTE provider status is not ok, rather than raising an error.
Spyderproxy Reseller API · Base URL https://spyderproxy.com/services/v1/reseller · Authenticate every request with Authorization: Token <YOUR_RESELLER_API_KEY>