On this pageReseller API overview
- Reseller API overview
- Base endpoint
- Authentication
- Method 1 — JSON body fields
- Method 2 — X-API-* headers
- Method 3 — HTTP Basic auth
- Request and response conventions
- Standard error codes
- Actions reference
- Connection & account
- TestConnection
- GetCredits
- GetProducts
- GetCustomFields
- Provisioning
- TestCreate — the safe dry-run
- Create
- GetServiceInfo
- GetOrders
- SetServiceNote
- Lifecycle
- Suspend
- Unsuspend
- ChangePassword
- Renew
- Upgrade
- Terminate
- Managing the proxies inside a service
- Permissions
- Idempotency & rate limiting
- Idempotency
- Rate limiting
- Quickstart
- cURL
- Python
The Reseller API is the proxy reseller API for ordering, provisioning, and managing ColdProxy services at scale. It is the wholesale provisioning interface for partners who buy ColdProxy plans in volume and resell them to their own customers, with every order paid from a prepaid reseller credit balance. Use it to order new services, run the full lifecycle, and track your balance over a single JSON HTTP endpoint. It is the B2B layer above the per-service Customer Plan API: the Reseller API manages services as billable units (order, suspend, renew), while the per-service API manages the proxies inside a single plan.
Reseller API overview
The Reseller API lets you run your entire ColdProxy supply chain over a single JSON HTTP endpoint. With it you can:
- Look up the products, pricing, and configuration options available to your reseller account.
- Order and provision new proxy services in real time.
- Manage the full service lifecycle: suspend, unsuspend, change passwords, upgrade, renew, and terminate.
- Track your orders and your prepaid reseller credit balance.
Who it is for. This API is built for resellers and platform partners who provision ColdProxy services on behalf of their own customers: for example, a proxy marketplace, a SaaS product that bundles proxies, or an agency that manages many client subscriptions. If you only need to manage a single plan you already purchased, use the Customer Plan API in that plan's settings instead. For program context, see /blog/proxy-reseller-program-infrastructure/. Not a reseller yet? Apply through the ColdProxy reseller program.
How billing works. Every provisioning and renewal action is charged against your prepaid reseller credit balance. Invoices are settled automatically from that balance; you never pay one manually. As long as your balance covers the order, the action completes immediately. You top up your balance in the reseller portal and check it any time with GetCredits.
Base endpoint
All requests are a single POST to:
POST https://members.coldproxy.com/modules/addons/coldproxy_product_reseller/api/Send a JSON body, set Content-Type: application/json, and choose the operation with the action field. There is one endpoint for every action; you never change the URL.
Authentication
Every request is authenticated with two values tied to your reseller account:
| Credential | What it is |
|---|---|
| username | The reseller account email address. |
| api_key | A secret key generated in your reseller portal. Typically 32 characters (configurable 16–64). |
Sign in to the ColdProxy reseller portal and open your API settings to generate the api_key. Treat it like a password: it grants full programmatic control of your reseller account and your prepaid balance.
Never commit your api_key to source control, embed it in client-side code, or share it. If a key is exposed, regenerate it in the portal and update your integrations immediately.
You can supply your credentials in any one of three equivalent ways. Pick whichever fits your HTTP client, and use one method per request for clarity.
Method 1 — JSON body fields
Include username and api_key directly in the request body alongside the action.
curl -X POST "https://members.coldproxy.com/modules/addons/coldproxy_product_reseller/api/" \
-H "Content-Type: application/json" \
-d '{
"action": "TestConnection",
"username": "you@example.com",
"api_key": "YOUR_32_CHAR_OR_LONGER_API_KEY"
}'Method 2 — X-API-* headers
Send the credentials as request headers and keep the body to just the action and its parameters.
curl -X POST "https://members.coldproxy.com/modules/addons/coldproxy_product_reseller/api/" \
-H "Content-Type: application/json" \
-H "X-API-Username: you@example.com" \
-H "X-API-Key: YOUR_32_CHAR_OR_LONGER_API_KEY" \
-d '{ "action": "TestConnection" }'Method 3 — HTTP Basic auth
Pass username:api_key as standard HTTP Basic credentials. Most HTTP libraries handle the Base64 encoding for you.
curl -X POST "https://members.coldproxy.com/modules/addons/coldproxy_product_reseller/api/" \
-H "Content-Type: application/json" \
-u "you@example.com:YOUR_32_CHAR_OR_LONGER_API_KEY" \
-d '{ "action": "TestConnection" }'All three are equivalent. The examples in the rest of this reference put credentials in the JSON body for readability, but you can switch to headers or Basic auth at any time.
Request and response conventions
Requests. Every request is an HTTP POST with a JSON body and Content-Type: application/json. The action field selects the operation; all other fields are the parameters for that action.
{
"action": "ActionName",
"username": "you@example.com",
"api_key": "YOUR_API_KEY",
"param_one": "value",
"param_two": "value"
}Responses. Every response is JSON and follows one envelope. A successful call returns result: "success" plus the action-specific data:
{
"result": "success"
}A failed call returns result: "error", a human-readable message, and a stable machine-readable code you can branch on:
{
"result": "error",
"message": "A human-readable explanation of what went wrong.",
"code": "ERROR_CODE"
}Always branch on the code field, not the message. Messages are written for humans and may be reworded over time; code values are stable. For the HTTP-level meaning of 429 and similar codes, see /blog/proxy-error-codes-407-403-429-502-and-504-explained/.
Standard error codes
| Code | HTTP | Meaning |
|---|---|---|
AUTH_REQUIRED |
401 | The request did not include credentials. |
INVALID_CREDENTIALS |
401 | The username or api_key is wrong. |
API_DISABLED |
403 | API access is disabled for your reseller account. |
GROUP_API_DISABLED |
403 | API access is disabled for your reseller group. |
IP_NOT_ALLOWED |
403 | The request came from an IP that is not on your account's IP allow-list. |
MISSING_ACTION |
400 | No action field was sent. |
INVALID_ACTION |
400 | The action value is not a recognized action (the match is case-sensitive). |
MISSING_PARAMETERS |
400 | A required parameter for the action is missing. |
PERMISSION_DENIED |
403 | The action is not enabled for your reseller group (see Permissions). |
PRODUCT_NOT_AVAILABLE |
400 | The requested product is not in your reseller catalog (Create, Upgrade). |
PRODUCT_NOT_ALLOWED |
403 | The action is not permitted on this service's product. Applies only to services that were not created through this API. |
SERVICE_NOT_FOUND |
404 | The service_id does not exist or does not belong to your account. One rare renewal-path lookup failure returns this code with HTTP 400. |
INVALID_STATUS |
400 | The service is not in a status that allows this action. |
REQUIRED_CONFIG_OPTIONS_MISSING |
400 | A Create request is missing one or more required product configuration options in options{}. |
INVALID_OPTIONS |
400 | The options{} payload is malformed (for example, not an object). |
INVALID_CONFIG_OPTION_VALUES |
400 | One or more values in options{} are not valid for the product. |
CUSTOM_FIELDS_VALIDATION_FAILED |
400 | One or more values in custom_fields{} failed validation (for example, a required custom field is missing or empty). |
INVALID_CUSTOM_FIELDS |
400 | The custom_fields{} payload is malformed (not an object) or names a field the product does not have. |
PAYMENT_REQUIRED |
402 | Your balance could not cover a Create or Upgrade. The order is cancelled automatically and nothing is charged — top up and retry. |
INSUFFICIENT_CREDITS |
400 | Your balance could not cover a Renew. The renewal invoice stays open, and your next Renew call pays that same invoice. |
REQUEST_IN_PROGRESS |
409 | Another request for the same account, service, or idempotency_key is still being processed. Retry after a short wait. |
IDEMPOTENCY_KEY_CONFLICT |
409 | The same idempotency_key was reused with a different payload. |
RATE_LIMIT_EXCEEDED |
429 | You have exceeded your request rate limit. |
PAYLOAD_TOO_LARGE |
413 | The JSON request body is larger than 1MB. |
SYSTEM_ERROR |
500 | Something failed on our side. Retry later or contact support. |
The response field shapes shown throughout this reference are illustrative: they show the keys you can rely on plus representative values. Optional or environment-specific fields may also be present; treat unknown fields as additive and forward-compatible.
Actions reference
There are 15 actions, grouped by purpose:
| Action | Group | What it does |
|---|---|---|
TestConnection |
Connection & account | Verify your credentials and connectivity. |
GetCredits |
Connection & account | Your prepaid credit balance and credit history. |
GetProducts |
Connection & account | List resellable products with pricing and options. |
GetCustomFields |
Connection & account | Custom fields a product defines and what they accept. |
TestCreate |
Provisioning | Validate a Create payload with no charge and no provisioning. |
Create |
Provisioning | Order and pay for a new service from your credit balance. |
GetServiceInfo |
Provisioning | Service details, real proxy credentials, per-service API access. |
GetOrders |
Provisioning | Paginated list of your services, with optional filters. |
SetServiceNote |
Provisioning | Attach or update an internal note on a service. |
Suspend |
Lifecycle | Suspend an active service. |
Unsuspend |
Lifecycle | Reactivate a suspended service. |
ChangePassword |
Lifecycle | Set a new proxy-authentication password. |
Renew |
Lifecycle | Renew one billing period from your credit balance. |
Upgrade |
Lifecycle | Move a service to a different product or billing cycle. Disabled by default. |
Terminate |
Lifecycle | Permanently end a service, immediately and irreversibly. Disabled by default. |
Each action below lists its purpose, parameters, a copy-paste request, and a representative success response.
Connection & account
TestConnection
Purpose: Verify that your credentials and connectivity are working. Use it as a health check before running real provisioning logic.
Parameters: none beyond authentication.
{
"action": "TestConnection",
"username": "you@example.com",
"api_key": "YOUR_API_KEY"
}Success response (illustrative):
{
"result": "success",
"message": "API connection successful",
"version": "1.8.15",
"timestamp": "2026-06-02 12:00:00"
}You can also call TestConnection with no credentials at all, as a plain availability ping. That variant replies with "message": "API is online" and a numeric Unix timestamp.
GetCredits
Purpose: Return your current prepaid reseller credit balance and a paginated history of credit movements. Check this before bulk provisioning so you do not run out of balance mid-batch.
| Parameter | Required | Description |
|---|---|---|
page |
optional | Page number for the credit history. |
limit |
optional | Items per page (default 20, max 100). |
{
"action": "GetCredits",
"username": "you@example.com",
"api_key": "YOUR_API_KEY",
"page": 1
}Success response (illustrative):
{
"result": "success",
"credits": {
"balance": 250.0,
"currency": { "code": "USD", "prefix": "$", "suffix": "" },
"formatted": "$250.00"
},
"transactions": [
{
"id": 1235,
"date": "2026-06-01 10:00:00",
"description": "Invoice paid from credit",
"amount": -12.0
},
{
"id": 1234,
"date": "2026-05-30 09:00:00",
"description": "Balance top-up",
"amount": 100.0
}
],
"pagination": { "page": 1, "limit": 20, "total": 2, "total_pages": 1, "has_more": false }
}Your balance and currency live inside the credits object. Transaction amounts are signed numbers (spending shows as negative entries) and the list is sorted newest first.
GetProducts
Purpose: List the products available to your reseller account, with their pricing, configuration options, and custom fields. This is the source of truth for building a valid Create request; read it first so you know which options{} and custom_fields{} a product requires. Pass an optional product_id to scope the response to a single product.
| Parameter | Required | Description |
|---|---|---|
product_id |
optional | Return only this product instead of the full catalog. |
{
"action": "GetProducts",
"username": "you@example.com",
"api_key": "YOUR_API_KEY"
}Success response (illustrative):
{
"result": "success",
"products": [
{
"id": 101,
"name": "Premium Residential Geo Target IPv4 (Unmetered)",
"description": "Speed-tier residential plan with geo targeting.",
"domain_required": false,
"pricing": {
"monthly": {
"label": "Monthly",
"base_price": 45.0,
"min_config_price": 0.0,
"total_price": 45.0,
"setup": 0.0
}
},
"options": [
{
"name": "Speed",
"key": "speed",
"type": "dropdown",
"values": [
{ "value": "25 Mbps", "label": "25 Mbps", "pricing": { "monthly": 0.0 } },
{ "value": "50 Mbps", "label": "50 Mbps", "pricing": { "monthly": 25.0 } }
]
}
],
"custom_fields": []
}
],
"total": 1,
"currency": { "code": "USD", "prefix": "$", "suffix": "" }
}The billing cycles a product supports are the keys of its pricing object; read them from there instead of hardcoding a list. Every visible dropdown or radio option in options must be sent in your Create request, using the option's key.
When a promotion applies to your account, the pricing cycles the promotion covers also include original_price and discount (with total_price already discounted), and each option value's pricing entry becomes an object ({"price": ..., "original_price": ..., "discount": ...}) instead of a plain number. Build your parser to accept both shapes. If no products are assigned to your account yet, the response is "products": [] with a message, and the total and currency keys are absent.
The four ColdProxy proxy products you can resell:
- Premium Residential Geo Target IPv4 (Unmetered) — speed-tier (Mbps) residential plan, 195+ countries, sticky sessions from 5s to 24h. Billed hourly, daily, weekly, or monthly.
- Premium Residential Geo Target IPv4 (GB Based) — monthly traffic packs, 195+ countries, sticky sessions from 5s to 24h. Monthly billing only.
- Residential IPv6 — speed-tier (Mbps) USA plan that includes a /32 subnet, sticky sessions from 5s to FOREVER. Billed hourly, daily, weekly, or monthly.
- Datacenter IPv6 — speed-tier (Mbps) plan across 25 supported countries and 47 locations (plus an "All Country" random option), a private /48 per location, sticky sessions from 5s to FOREVER, and CDN-aware IPv6 reachability for supported CDN-fronted domains. Billed daily, weekly, or monthly.
Always read live values from GetProducts rather than hardcoding prices or option lists. Pricing, available speed tiers, and configuration options can change, and your reseller account may see a tailored catalog. The product_id values (101/102) in these examples are placeholders; use the IDs returned by GetProducts. See /pricing/ for the public lineup.
GetCustomFields
Purpose: Return the custom fields defined for a specific product, including which are required and what values they accept. Use it to build the custom_fields{} object for Create when a product needs more than configuration options.
| Parameter | Required | Description |
|---|---|---|
product_id |
required | The product whose custom fields you want. |
{
"action": "GetCustomFields",
"username": "you@example.com",
"api_key": "YOUR_API_KEY",
"product_id": 101
}Success response (illustrative):
{
"result": "success",
"product_id": 101,
"product_name": "Premium Residential Geo Target IPv4 (Unmetered)",
"custom_fields": [
{
"name": "Label",
"type": "text",
"required": false,
"description": "A label for your own reference.",
"options": [],
"regexpr": ""
}
],
"total": 1
}regexpr is the validation pattern a field value must match in Create (an empty string means no pattern). Use the field's name as the key in your custom_fields{} object.
Provisioning
TestCreate — the safe dry-run
Purpose: Validate a Create request without charging your balance or provisioning anything. TestCreate runs the same validation as Create (config options, custom fields, domain requirement) and returns a simulated result that mirrors a real Create response: status and provisioned echo what a successful order would return. The test: true flag, the _test_info block, and the "No charges applied" message confirm nothing was actually created. It is exempt from rate limiting, so you can call it freely while building and testing your integration.
Always run TestCreate first when you add support for a new product or change your Create payload.
Parameters: identical to Create (see below), except idempotency_key, which TestCreate ignores.
{
"action": "TestCreate",
"username": "you@example.com",
"api_key": "YOUR_API_KEY",
"product_id": 101,
"billing_cycle": "monthly",
"options": { "Speed": "25 Mbps" },
"custom_fields": {}
}Success response (illustrative):
{
"result": "success",
"message": "Test order validated successfully. No charges applied.",
"test": true,
"order_id": 612345,
"invoice_id": 612346,
"service_id": 612347,
"product_id": 101,
"billing_cycle": "monthly",
"amount_paid": 45.0,
"status": "Active",
"provisioned": true,
"created_date": "2026-06-02",
"next_due_date": "2026-07-02",
"username": "test_user_1a2b3c4d",
"password": "***",
"_test_info": {
"validation_passed": true,
"sufficient_credits": true,
"current_balance": 250.0,
"would_charge": 45.0,
"options_validated": 1,
"custom_fields_validated": 0
}
}would_charge is an estimate: the product's base price plus setup fee, after any discount. It does not include configurable-option pricing, so the real Create charge can be higher on products with priced options. The test: true flag also appears on TestCreate error responses.
Create
Purpose: Order and pay for a new service in one call, from your prepaid reseller credit balance. On success the order is placed and paid; check status and provisioned in the response, because the service may still be Pending while provisioning completes.
| Parameter | Required | Description |
|---|---|---|
product_id |
required | The product to order (from GetProducts). |
billing_cycle |
required | A billing cycle the product supports. Read the exact cycle keys from the product's pricing object in GetProducts (for example monthly). |
options |
required if the product has config options | Object of configuration option values. |
custom_fields |
required if the product has required custom fields | Object of custom field values. |
domain |
only if the product requires it | Domain value for products that need one. |
idempotency_key |
optional | Safe-retry key — see Idempotency & rate limiting. |
Create validation rules:
options{}— every visible dropdown/radio configuration option for the product is required. Missing options returnREQUIRED_CONFIG_OPTIONS_MISSING; invalid values returnINVALID_CONFIG_OPTION_VALUES; a malformedoptions{}payload (not an object) returnsINVALID_OPTIONS.custom_fields{}— every required custom field must pass validation. Missing or invalid values returnCUSTOM_FIELDS_VALIDATION_FAILED; a malformed payload or an unknown field name returnsINVALID_CUSTOM_FIELDS.domain— only include it when the product requires a domain. Omit it otherwise.
Use GetProducts and GetCustomFields to discover exactly which options and fields a product needs, and validate with TestCreate before going live.
{
"action": "Create",
"username": "you@example.com",
"api_key": "YOUR_API_KEY",
"product_id": 101,
"billing_cycle": "monthly",
"options": { "Speed": "25 Mbps" },
"custom_fields": {},
"idempotency_key": "order-2026-06-02-abc123"
}Success response (illustrative):
{
"result": "success",
"message": "Order created successfully",
"order_id": 50231,
"invoice_id": 90230,
"service_id": 80417,
"product_id": 101,
"billing_cycle": "monthly",
"amount_paid": 45.0,
"status": "Pending",
"provisioned": false,
"created_date": "2026-06-02",
"username": "user80417",
"password": "***"
}A paid order with "status": "Pending" and "provisioned": false is a normal result; provisioning finishes shortly after. Poll GetServiceInfo until the service is Active. The password field is always masked as ***; read the real credentials from GetServiceInfo. next_due_date, domain, username, and password appear only when they have values.
If your balance cannot cover the order, you get HTTP 402 with code PAYMENT_REQUIRED. The just-created order is cancelled automatically and nothing is charged; top up your balance and retry safely.
Residential IPv4 (GB Based) and Residential IPv6 activate instantly after payment clears. Residential IPv4 (Unmetered) and Datacenter IPv6 start automatic setup after payment clears; allow up to 10 minutes and connect as soon as setup completes. See Activation and setup times. Manage the proxies inside a service (proxy lists, authorized IPs, geo targeting) with the per-service Customer Plan API, not this endpoint.
GetServiceInfo
Purpose: Return the current details and status of a service on your reseller account, including the service's real proxy credentials and, for proxy services, the per-service API access details.
| Parameter | Required | Description |
|---|---|---|
service_id |
required | The service to look up. |
{
"action": "GetServiceInfo",
"username": "you@example.com",
"api_key": "YOUR_API_KEY",
"service_id": 80417
}Success response (illustrative):
{
"result": "success",
"service": {
"id": 80417,
"order_id": 50231,
"product_id": 101,
"product_name": "Premium Residential Geo Target IPv4 (Unmetered)",
"username": "user80417",
"password": "pr0xy-Example-Pass",
"status": "Active",
"billing_cycle": "Monthly",
"price": 45.0,
"registration_date": "2026-06-02",
"next_due_date": "2026-07-02",
"suspend_reason": null,
"reseller_api": true,
"client_note": null
},
"options": [
{ "key": "speed", "name": "Speed", "value": "25 Mbps" }
],
"custom_fields": {},
"api": {
"endpoint": "https://members.coldproxy.com/newsysapi.php",
"key": "EXAMPLE-SERVICE-KEY-DO-NOT-USE",
"service_url": "https://members.coldproxy.com/clientarea.php?action=productdetails&id=80417",
"description": "To find all available APIs to control your plan, check the service page at: https://members.coldproxy.com/clientarea.php?action=productdetails&id=80417"
}
}The service details are nested under service, with options, custom_fields, and api as siblings. This is where you read the real username and password after Create. Status values are capitalized (Active, Pending, Suspended, Terminated), and billing_cycle is a display label. The keys domain, dedicated_ip, assigned_ips, and expiry_timestamp appear only when they have values.
The api object is the gateway to per-service proxy management; see Managing the proxies inside a service. It is null when per-service credentials are not available (for example, right after Create while provisioning is still running).
GetOrders
Purpose: Return a paginated list of the services on your reseller account, with optional filters. Each item represents one service; order_id links it to its order when one exists.
| Parameter | Required | Description |
|---|---|---|
status |
optional | Filter by service status. Matching is case-insensitive (e.g. active, suspended, terminated). |
product_id |
optional | Filter by product. |
include_all_services |
optional | Default false returns only services created through this API. Set true to also list every other service on your account (those have "created_via_api": false). |
page |
optional | Page number. |
limit |
optional | Items per page (default 50, max 100). |
{
"action": "GetOrders",
"username": "you@example.com",
"api_key": "YOUR_API_KEY",
"status": "active",
"page": 1
}Success response (illustrative):
{
"result": "success",
"orders": [
{
"order_id": 50231,
"service_id": 80417,
"product_id": 101,
"product_name": "Premium Residential Geo Target IPv4 (Unmetered)",
"domain": "",
"status": "Active",
"billing_cycle": "Monthly",
"amount": 45.0,
"registration_date": "2026-06-02",
"next_due_date": "2026-07-02",
"terminated_on": null,
"created_at": "2026-06-02 12:00:00",
"created_via_api": true
}
],
"pagination": { "page": 1, "limit": 50, "total": 1, "total_pages": 1, "has_more": false }
}amount is the service's current renewal price, not the amount you originally paid for the order. order_id can be null for services that have no order. Returned status values are capitalized.
SetServiceNote
Purpose: Attach or update a short internal note on a service you provisioned (for example, your own customer reference). The note is stored on the service in the members portal.
| Parameter | Required | Description |
|---|---|---|
service_id |
required | The service to annotate. |
note |
optional | The note text — max 200 characters, HTML is removed automatically. Omit it or send an empty value to clear the note. |
{
"action": "SetServiceNote",
"username": "you@example.com",
"api_key": "YOUR_API_KEY",
"service_id": 80417,
"note": "Customer: Acme Corp — renewed 2026-06"
}Success response (illustrative):
{
"result": "success",
"service_id": 80417,
"client_note": "Customer: Acme Corp — renewed 2026-06",
"action": "saved"
}Lifecycle
Suspend
Purpose: Suspend an active service (for example, when your customer's subscription lapses). An optional reason is stored with the suspension.
| Parameter | Required | Description |
|---|---|---|
service_id |
required | The service to suspend. |
reason |
optional | A short reason recorded with the suspension (up to 255 characters). A standard note is used when omitted. |
{
"action": "Suspend",
"username": "you@example.com",
"api_key": "YOUR_API_KEY",
"service_id": 80417,
"reason": "Customer subscription unpaid"
}Success response (illustrative):
{
"result": "success",
"service_id": 80417,
"status": "Suspended",
"suspend_reason": "Customer subscription unpaid",
"suspended_date": "2026-06-10 14:02:11"
}Unsuspend
Purpose: Reactivate a suspended service.
| Parameter | Required | Description |
|---|---|---|
service_id |
required | The service to reactivate. |
{
"action": "Unsuspend",
"username": "you@example.com",
"api_key": "YOUR_API_KEY",
"service_id": 80417
}Success response (illustrative):
{
"result": "success",
"service_id": 80417,
"status": "Active",
"unsuspended_date": "2026-06-10 15:20:43"
}Only services suspended through this API can be unsuspended; lifting a suspension made by ColdProxy staff or billing returns UNSUSPEND_NOT_ALLOWED. A service with an overdue renewal invoice returns OVERDUE_INVOICES; renew it first, then unsuspend.
ChangePassword
Purpose: Set a new password for a service's proxy authentication.
| Parameter | Required | Description |
|---|---|---|
service_id |
required | The service whose password to change. |
password |
required | The new password to set — 6 to 128 characters (the minimum is configurable, 6 by default; too short or too long returns INVALID_PASSWORD). |
{
"action": "ChangePassword",
"username": "you@example.com",
"api_key": "YOUR_API_KEY",
"service_id": 80417,
"password": "new-strong-password"
}Success response (illustrative):
{
"result": "success",
"message": "Password changed successfully",
"service_id": 80417,
"changed_date": "2026-06-10 14:02:11"
}Works on Active or Suspended services; other statuses return INVALID_STATUS.
Changing the password invalidates any user:pass proxy strings already issued for that service. Re-pull the service's proxy list afterward so your customer's workers keep authenticating.
Renew
Purpose: Renew a service for one billing period, charged to your prepaid reseller credit balance; for a monthly service this advances the next due date by one month. There is no multi-period parameter; call Renew once per period. Works on Active or Suspended services.
| Parameter | Required | Description |
|---|---|---|
service_id |
required | The service to renew. |
idempotency_key |
optional | Safe-retry key — see Idempotency & rate limiting. |
{
"action": "Renew",
"username": "you@example.com",
"api_key": "YOUR_API_KEY",
"service_id": 80417,
"idempotency_key": "renew-80417-2026-06"
}Success response (illustrative): renewing a monthly service whose next_due_date was 2026-07-02 advances it by one month to 2026-08-02:
{
"result": "success",
"service_id": 80417,
"invoice_id": 90231,
"amount_paid": 45.0,
"billing_cycle": "Monthly",
"next_due_date": "2026-08-02"
}billing_cycle in the Renew response is a display label (for example Monthly), not the lowercase cycle key you send to Create. next_due_date appears when the service has a known due date.
If your balance cannot cover the renewal, you get HTTP 400 with code INSUFFICIENT_CREDITS. The renewal invoice stays open; your next Renew call for that service pays the same invoice, so retrying never creates duplicate invoices or charges.
Upgrade
Purpose: Move a service to a different product (or a different billing cycle) without terminating it. The price difference is calculated for you: an upgrade is charged to your prepaid reseller credit balance, and a downgrade is returned to that balance as credit.
| Parameter | Required | Description |
|---|---|---|
service_id |
required | The service to change. The service must be Active. |
new_product_id |
required | The target product (from GetProducts). |
billing_cycle |
optional | Billing cycle for the new product. Defaults to the service's current cycle; it must be available on the target product. |
idempotency_key |
optional | Safe-retry key — see Idempotency & rate limiting. |
{
"action": "Upgrade",
"username": "you@example.com",
"api_key": "YOUR_API_KEY",
"service_id": 80417,
"new_product_id": 102,
"billing_cycle": "monthly",
"idempotency_key": "upgrade-80417-2026-06"
}Success response (illustrative):
{
"result": "success",
"message": "Service upgraded successfully",
"service_id": 80417,
"upgrade_order_id": 50298,
"invoice_id": 90312,
"old_product_id": 101,
"old_product_name": "Premium Residential Geo Target IPv4 (Unmetered)",
"new_product_id": 102,
"new_product_name": "Premium Residential Geo Target IPv4 (GB Based)",
"billing_cycle": "monthly",
"status": "Active",
"type": "upgrade",
"amount_paid": 12.5
}type tells you which way the change went. On an "upgrade" you pay amount_paid from credit. On a "downgrade" the response carries refund_amount instead, and that amount is returned to your credit balance. Requesting the product and cycle the service already has is a no-op: you get success with already_applied: true and no charge.
If your balance cannot cover the upgrade, you get HTTP 402 with code PAYMENT_REQUIRED. The upgrade is rolled back and nothing is charged; top up and retry safely.
Upgrade and Terminate are disabled for reseller accounts by default. If you receive PERMISSION_DENIED, ask your ColdProxy account manager to enable them for your group.
Terminate
Purpose: Permanently end a service. Termination is immediate (the proxies stop working as soon as the call succeeds) and the service cannot be brought back through this API.
| Parameter | Required | Description |
|---|---|---|
service_id |
required | The service to terminate. |
{
"action": "Terminate",
"username": "you@example.com",
"api_key": "YOUR_API_KEY",
"service_id": 80417
}Success response (illustrative):
{
"result": "success",
"message": "Service terminated successfully",
"service_id": 80417,
"status": "Terminated",
"terminated_date": "2026-06-10 14:02:11"
}Any service that is not already terminated or cancelled can be terminated, including suspended ones. Calling it again returns ALREADY_TERMINATED.
Terminate is permanent. If you only need to pause a service (for example while your customer settles a bill), use Suspend instead; that is reversible with Unsuspend. Like Upgrade, this action is disabled by default (see the note above).
Managing the proxies inside a service
The Reseller API manages services as billable units: you order, renew, suspend, and terminate them. Everything that happens inside a service (generating proxy lists, the IP allow-list, geo targeting, usage, bandwidth top-ups, password rotation) belongs to the per-service Customer Plan API.
You do not need the client area to use it. For every proxy service you provision, GetServiceInfo returns that service's API endpoint and key in its api field:
"api": {
"endpoint": "https://members.coldproxy.com/newsysapi.php",
"key": "EXAMPLE-SERVICE-KEY-DO-NOT-USE",
"service_url": "https://members.coldproxy.com/clientarea.php?action=productdetails&id=80417",
"description": "To find all available APIs to control your plan, check the service page at: https://members.coldproxy.com/clientarea.php?action=productdetails&id=80417"
}Call the Customer Plan API with the service ID and that key:
GET https://members.coldproxy.com/newsysapi.php?id=80417&key=EXAMPLE-SERVICE-KEY-DO-NOT-USE&a=infoA complete integration uses the two APIs together:
- Order a service with
Create(Reseller API). - Read
api.endpointandapi.keyfromGetServiceInfo(Reseller API). - Operate the proxies (generate lists, authorize IPs, watch usage) with the Customer Plan API.
- Bill —
Renew,Suspend,Unsuspend, orTerminateas your customer's subscription changes (Reseller API).
For white-label delivery, pass hostname=no to the Customer Plan API proxies action, or turn off the client area's Use Hostname instead of IP option, to deliver proxy lists as IP:port instead of the gateway hostname.
api is null when the per-service credentials are not available yet: most commonly right after Create, before provisioning finishes. Wait for the service to become Active and call GetServiceInfo again. Treat api.key like a password: it grants full control of that service's proxies.
Permissions
Available actions and products are controlled per reseller group. Your account inherits its permissions from the group an administrator assigns it to. Most actions in this reference are enabled for reseller accounts by default; two are not: Upgrade and Terminate ship disabled and must be switched on for your group. Ask your ColdProxy account manager if you need them.
If you call an action your group is not permitted to use, you receive PERMISSION_DENIED (your credentials are valid, but the action is not enabled for your group). An unrecognized action value returns INVALID_ACTION. Product access works separately: ordering a product that is not in your catalog returns PRODUCT_NOT_AVAILABLE, and managing an existing service whose product does not permit that action returns PRODUCT_NOT_ALLOWED (this applies only to services that were not created through this API).
To add products to your catalog or request additional permissions for your group, contact your ColdProxy account manager.
Idempotency & rate limiting
Idempotency
Create, Upgrade, and Renew are charging actions. To make them safe to retry after a timeout or network blip without double-charging, send an optional idempotency_key: any unique string you generate per logical operation (for example, your own order reference; up to 191 characters).
- If the original request succeeded, retrying with the same key returns the saved response instead of running the operation again. No second charge.
- If the original request failed, the key is released; retrying with the same key runs the operation fresh.
- If a request with that key is still being processed when a duplicate arrives, the duplicate returns HTTP
409with codeREQUEST_IN_PROGRESS. Wait briefly and retry. - If you reuse a key with a different payload, you get HTTP
409with codeIDEMPOTENCY_KEY_CONFLICT.
Use a fresh idempotency_key for each distinct operation, and reuse the same key only when retrying that exact operation.
Rate limiting
Requests can be rate-limited per reseller account; your administrator enables and sizes the limit. When you exceed it, the API returns HTTP 429 with code RATE_LIMIT_EXCEEDED, a retry_after field in the body, and these headers:
| Header | Meaning |
|---|---|
Retry-After |
Seconds to wait before retrying. |
X-RateLimit-Limit |
Your request allowance for the window. |
X-RateLimit-Remaining |
Requests remaining in the current window. |
X-RateLimit-Reset |
Unix timestamp when the current window resets. |
Successful responses also carry the X-RateLimit-Limit and X-RateLimit-Remaining headers (X-RateLimit-Remaining is -1 when no limit is active). Respect Retry-After and use exponential backoff for resilient automation.
TestCreate is exempt from rate limiting. You can validate Create payloads as often as you need while building and testing, without consuming your rate budget.
Quickstart
This quickstart authenticates, lists your available products, then dry-runs a Create with TestCreate, all without charging your balance or provisioning anything.
cURL
BASE="https://members.coldproxy.com/modules/addons/coldproxy_product_reseller/api/"
USER="you@example.com"
KEY="YOUR_32_CHAR_OR_LONGER_API_KEY"
# 1. Verify credentials and connectivity
curl -X POST "$BASE" \
-H "Content-Type: application/json" \
-d "{\"action\":\"TestConnection\",\"username\":\"$USER\",\"api_key\":\"$KEY\"}"
# 2. List the products you can resell
curl -X POST "$BASE" \
-H "Content-Type: application/json" \
-d "{\"action\":\"GetProducts\",\"username\":\"$USER\",\"api_key\":\"$KEY\"}"
# 3. Dry-run an order (no charge, no provisioning)
curl -X POST "$BASE" \
-H "Content-Type: application/json" \
-d "{
\"action\":\"TestCreate\",
\"username\":\"$USER\",
\"api_key\":\"$KEY\",
\"product_id\":101,
\"billing_cycle\":\"monthly\",
\"options\":{\"Speed\":\"25 Mbps\"},
\"custom_fields\":{}
}"Python
import requests
BASE = "https://members.coldproxy.com/modules/addons/coldproxy_product_reseller/api/"
AUTH = {
"username": "you@example.com",
"api_key": "YOUR_32_CHAR_OR_LONGER_API_KEY",
}
def call(action, **params):
payload = {"action": action, **AUTH, **params}
resp = requests.post(BASE, json=payload, timeout=30)
data = resp.json()
if data.get("result") != "success":
raise RuntimeError(f"{data.get('code')}: {data.get('message')}")
return data
# 1. Verify credentials and connectivity
print(call("TestConnection"))
# 2. List the products you can resell
products = call("GetProducts")["products"]
for p in products:
print(p["id"], p["name"], list(p["pricing"].keys()))
# 3. Dry-run an order (no charge, no provisioning)
dry_run = call(
"TestCreate",
product_id=101,
billing_cycle="monthly",
options={"Speed": "25 Mbps"},
custom_fields={},
)
print("Test mode:", dry_run.get("test"))
print("Estimated charge:", dry_run.get("amount_paid"))Once TestConnection succeeds, GetProducts shows your real catalog, and TestCreate returns test: true with provisioned: true, switch the TestCreate call to Create (and add an idempotency_key) to provision a live service. Watch your prepaid reseller credit balance with GetCredits so bulk runs never stall mid-batch, and manage the proxies inside each service with the Customer Plan API. For broader integration patterns, see /blog/proxy-automation-api-integration-guide/.