ISP Proxies API

ISP proxies are discrete, static IP:port credentials assigned to your account — a fundamentally different model from the residential gateway. Where residential proxies share a single rotating gateway host (gate.proxyhat.com) and meter a byte pool across many sub-users, an ISP proxy is a dedicated fixed endpoint with its own IP, login and password that you connect to directly over HTTP or SOCKS5. These endpoints return the standard {success, payload, meta, errors, description} envelope.

Every endpoint on this page requires ISP proxy access. They are only available to accounts with the has_isp_proxy_access flag enabled (check the has_isp_proxy_access field on GET /v1/auth/user). Without it every call returns 403 in the standard envelope: { "success": false, "payload": null, "errors": { "access": "ISP proxy access is not enabled for your account." }, "description": "Access denied" }.

List My ISP Proxies

GET /v1/isp-proxies Requires Auth

List My ISP Proxies

List My ISP Proxies

Return every ISP proxy assigned to the authenticated account, ordered by country then IP. The payload is a mixed array of two row kinds: live "proxy" rows (ready-to-use credentials) and "provisioning" rows (orders still being fulfilled). Distinguish them by the "kind" field. No cost or balance data is ever included.

No input needed — runs live with your key
curl https://api.proxyhat.com/v1/isp-proxies \
  -H "Authorization: Bearer __API_KEY__" \
  -H "Accept: application/json"
import requests

response = requests.get(
    "https://api.proxyhat.com/v1/isp-proxies",
    headers={
        "Authorization": "Bearer __API_KEY__",
        "Accept": "application/json",
    },
)

data = response.json()
for row in data["payload"]:
    if row["kind"] == "proxy":
        print(f"{row[\"isp_name\"]} {row[\"ip\"]}:{row[\"port\"]} -> {row[\"http_url\"]}")
    else:
        print(f"provisioning {row[\"isp_name\"]} (~{row[\"eta_hours\"]}h)")
const response = await fetch("https://api.proxyhat.com/v1/isp-proxies", {
  headers: {
    "Authorization": "Bearer __API_KEY__",
    "Accept": "application/json",
  },
});

const { payload } = await response.json();
payload.forEach(row => {
  if (row.kind === "proxy") {
    console.log(`${row.isp_name} ${row.ip}:${row.port} -> ${row.http_url}`);
  } else {
    console.log(`provisioning ${row.isp_name} (~${row.eta_hours}h)`);
  }
});
req, _ := http.NewRequest("GET", "https://api.proxyhat.com/v1/isp-proxies", nil)
req.Header.Set("Authorization", "Bearer __API_KEY__")
req.Header.Set("Accept", "application/json")

resp, err := http.DefaultClient.Do(req)
if err != nil {
    log.Fatal(err)
}
defer resp.Body.Close()

var out struct {
    Payload []map[string]interface{} `json:"payload"`
}
json.NewDecoder(resp.Body).Decode(&out)
for _, row := range out.Payload {
    fmt.Printf("%v %v\n", row["kind"], row["isp_name"])
}
Two row kinds. A "proxy" row carries the full live credentials (ip, port, login, password) plus both ready-to-paste connection URLs (http_url, socks5_url). A "provisioning" row represents an order still being fulfilled (pending / provisioning / needs-attention) and carries only isp_name, country_code, category, an eta_hours estimate and queued_at — poll this endpoint until it flips to a "proxy" row. subscription_status is null when the proxy is not tied to a subscription.

ISP Store Catalog

GET /v1/isp-store/catalog Requires Auth

Browse ISP Store Catalog

Browse ISP Store Catalog

Return the purchasable ISP-proxy catalog — every active plan, ordered by country then ISP name. Each item is annotated with an "affordable" boolean computed against your account balance (cost figures themselves are never exposed). The payload is cached for 90 seconds.

No input needed — runs live with your key
curl https://api.proxyhat.com/v1/isp-store/catalog \
  -H "Authorization: Bearer __API_KEY__" \
  -H "Accept: application/json"
import requests

response = requests.get(
    "https://api.proxyhat.com/v1/isp-store/catalog",
    headers={
        "Authorization": "Bearer __API_KEY__",
        "Accept": "application/json",
    },
)

data = response.json()
print("max per order:", data["meta"]["max_buy_qty"])
for item in data["payload"]:
    tag = "buy" if item["affordable"] else "request"
    print(f"{item[\"isp_name\"]} ({item[\"country_code\"]}) ${item[\"price\"]} [{tag}]")
const response = await fetch("https://api.proxyhat.com/v1/isp-store/catalog", {
  headers: {
    "Authorization": "Bearer __API_KEY__",
    "Accept": "application/json",
  },
});

const { payload, meta } = await response.json();
console.log("max per order:", meta.max_buy_qty);
payload.forEach(item => {
  const tag = item.affordable ? "buy" : "request";
  console.log(`${item.isp_name} (${item.country_code}) $${item.price} [${tag}]`);
});
req, _ := http.NewRequest("GET", "https://api.proxyhat.com/v1/isp-store/catalog", nil)
req.Header.Set("Authorization", "Bearer __API_KEY__")
req.Header.Set("Accept", "application/json")

resp, err := http.DefaultClient.Do(req)
if err != nil {
    log.Fatal(err)
}
defer resp.Body.Close()

var out struct {
    Payload []map[string]interface{} `json:"payload"`
    Meta    struct {
        MaxBuyQty   int  `json:"max_buy_qty"`
        RequestGate bool `json:"request_gate"`
    } `json:"meta"`
}
json.NewDecoder(resp.Body).Decode(&out)
fmt.Println("max per order:", out.Meta.MaxBuyQty)
for _, item := range out.Payload {
    fmt.Printf("%v (%v) $%v affordable=%v\n", item["isp_name"], item["country_code"], item["price"], item["affordable"])
}
Catalog fields. price is the sell price in currency; days is the subscription term; traffic_limit of 0 means the ISP proxy is unmetered. affordable tells you whether the plan can be bought outright right now — when it is false, open a top-up request with the tariff-request endpoint below instead. meta.max_buy_qty caps how many units may be bought in a single order, and meta.request_gate indicates whether direct purchase is gated behind the request flow.

Request a Tariff (Top-Up)

POST /v1/isp-store/tariff-request Requires Auth

Request a Tariff

Request a Tariff

Open a top-up request for an ISP plan you cannot yet afford. This posts a tagged message into your support conversation and alerts an admin to add balance. Deduplicated within a 24-hour window (a repeat call inside the window returns 200 without re-posting or re-notifying). Rate-limited to 10 requests per minute.

Example request: plan_id
Request Body
Name Type Required Description
plan_id string (uuid) Required The UUID of the ISP plan (the "id" from a catalog item) you want to request.
curl -X POST https://api.proxyhat.com/v1/isp-store/tariff-request \
  -H "Authorization: Bearer __API_KEY__" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{"plan_id": "8d2e1f4a-6b3c-4e9d-a12f-7c5b0e3d9a84"}'
import requests

response = requests.post(
    "https://api.proxyhat.com/v1/isp-store/tariff-request",
    headers={
        "Authorization": "Bearer __API_KEY__",
        "Content-Type": "application/json",
        "Accept": "application/json",
    },
    json={"plan_id": "8d2e1f4a-6b3c-4e9d-a12f-7c5b0e3d9a84"},
)

print(response.json())
const response = await fetch("https://api.proxyhat.com/v1/isp-store/tariff-request", {
  method: "POST",
  headers: {
    "Authorization": "Bearer __API_KEY__",
    "Content-Type": "application/json",
    "Accept": "application/json",
  },
  body: JSON.stringify({ plan_id: "8d2e1f4a-6b3c-4e9d-a12f-7c5b0e3d9a84" }),
});

console.log(await response.json());
body, _ := json.Marshal(map[string]string{
    "plan_id": "8d2e1f4a-6b3c-4e9d-a12f-7c5b0e3d9a84",
})

req, _ := http.NewRequest("POST", "https://api.proxyhat.com/v1/isp-store/tariff-request", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer __API_KEY__")
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Accept", "application/json")

resp, err := http.DefaultClient.Do(req)
if err != nil {
    log.Fatal(err)
}
defer resp.Body.Close()

var out map[string]interface{}
json.NewDecoder(resp.Body).Decode(&out)
fmt.Println(out)
This endpoint is only for plans you cannot afford. If the plan is already affordable the server returns 422 with { "success": false, "errors": { "plan": "This tariff is available — buy it directly." }, "description": "Plan is affordable" } — buy it directly instead. An unknown or inactive plan_id returns 404 { "message": "Not found" }, and a malformed (non-UUID) plan_id returns 422 validation error.

Get ISP Plan

GET /v1/plans/isp/{id} Requires Auth

Get ISP Plan

Get ISP Plan

Retrieve a single active ISP plan by its UUID, for a checkout / order-summary screen. Internal cost and markup fields are stripped from the response, and a "name" alias (equal to "isp_name") is added for convenience. Returns a flat plan object (NOT wrapped in the envelope); 404 if the plan does not exist or is inactive.

We filled these in for you: id

Tweak any value if you like — or just press Try.

Path Parameters
Name Type Required Description
id string (uuid) Required The UUID of the ISP plan (the "id" from a catalog item).
curl https://api.proxyhat.com/v1/plans/isp/8d2e1f4a-6b3c-4e9d-a12f-7c5b0e3d9a84 \
  -H "Authorization: Bearer __API_KEY__" \
  -H "Accept: application/json"
import requests

plan_id = "8d2e1f4a-6b3c-4e9d-a12f-7c5b0e3d9a84"

response = requests.get(
    f"https://api.proxyhat.com/v1/plans/isp/{plan_id}",
    headers={
        "Authorization": "Bearer __API_KEY__",
        "Accept": "application/json",
    },
)

plan = response.json()
print(f"{plan[\"name\"]} ({plan[\"country_code\"]}): ${plan[\"price_total\"]}")
const planId = "8d2e1f4a-6b3c-4e9d-a12f-7c5b0e3d9a84";

const response = await fetch(`https://api.proxyhat.com/v1/plans/isp/${planId}`, {
  headers: {
    "Authorization": "Bearer __API_KEY__",
    "Accept": "application/json",
  },
});

const plan = await response.json();
console.log(`${plan.name} (${plan.country_code}): $${plan.price_total}`);
planID := "8d2e1f4a-6b3c-4e9d-a12f-7c5b0e3d9a84"
url := fmt.Sprintf("https://api.proxyhat.com/v1/plans/isp/%s", planID)

req, _ := http.NewRequest("GET", url, nil)
req.Header.Set("Authorization", "Bearer __API_KEY__")
req.Header.Set("Accept", "application/json")

resp, err := http.DefaultClient.Do(req)
if err != nil {
    log.Fatal(err)
}
defer resp.Body.Close()

var plan map[string]interface{}
json.NewDecoder(resp.Body).Decode(&plan)
fmt.Printf("%s (%s): $%v\n", plan["name"], plan["country_code"], plan["price_total"])