Sub-User Groups API

Organize your proxy sub-users into logical groups. Groups are purely organizational containers scoped to your account — deleting a group never deletes its members, it simply moves them back to the unassigned pool. All endpoints return the standard resource envelope {success, payload, errors, description}.

A group object contains id (UUID), user_id, name, description, created_at, and updated_at. When listing groups, each item additionally carries sub_users_count (populated via a count query). This field is not present on the create or update responses — only the list endpoint returns it.

List Groups

GET /v1/sub-user-groups Requires Auth

List Sub-User Groups

List Sub-User Groups

Retrieve every sub-user group belonging to your account, ordered by creation time (oldest first). Each group includes sub_users_count, the number of sub-users currently assigned to it.

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

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

data = response.json()
for group in data["payload"]:
    print(f"{group[\"name\"]}: {group[\"sub_users_count\"]} sub-users")
const response = await fetch("https://api.proxyhat.com/v1/sub-user-groups", {
  headers: {
    "Authorization": "Bearer __API_KEY__",
    "Accept": "application/json",
  },
});

const data = await response.json();
data.payload.forEach(g => console.log(`${g.name}: ${g.sub_users_count} sub-users`));
req, _ := http.NewRequest("GET", "https://api.proxyhat.com/v1/sub-user-groups", 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 result struct {
    Payload []map[string]interface{} `json:"payload"`
}
json.NewDecoder(resp.Body).Decode(&result)
for _, g := range result.Payload {
    fmt.Printf("%s: %v sub-users\n", g["name"], g["sub_users_count"])
}

Create Group

POST /v1/sub-user-groups Requires Auth

Create Sub-User Group

Create Sub-User Group

Create a new group. Returns 201 with the created group. Note that sub_users_count is NOT included on this response — a freshly created group is always empty, and the count is only computed by the list endpoint.

Example request: name description
Request Body
Name Type Required Description
name string Required Group name. Maximum 100 characters.
description string Optional Optional notes about the group. Maximum 5000 characters.
curl -X POST https://api.proxyhat.com/v1/sub-user-groups \
  -H "Authorization: Bearer __API_KEY__" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "name": "Scrapers",
    "description": "Sub-users used for data collection"
  }'
import requests

response = requests.post(
    "https://api.proxyhat.com/v1/sub-user-groups",
    headers={
        "Authorization": "Bearer __API_KEY__",
        "Accept": "application/json",
    },
    json={
        "name": "Scrapers",
        "description": "Sub-users used for data collection",
    },
)

group = response.json()["payload"]
print(group["id"], group["name"])
const response = await fetch("https://api.proxyhat.com/v1/sub-user-groups", {
  method: "POST",
  headers: {
    "Authorization": "Bearer __API_KEY__",
    "Content-Type": "application/json",
    "Accept": "application/json",
  },
  body: JSON.stringify({
    name: "Scrapers",
    description: "Sub-users used for data collection",
  }),
});

const { payload } = await response.json();
console.log(payload.id, payload.name);
body := strings.NewReader(`{
  "name": "Scrapers",
  "description": "Sub-users used for data collection"
}`)

req, _ := http.NewRequest("POST", "https://api.proxyhat.com/v1/sub-user-groups", 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 result struct {
    Payload map[string]interface{} `json:"payload"`
}
json.NewDecoder(resp.Body).Decode(&result)
fmt.Println(result.Payload["id"], result.Payload["name"])

Validation failures return HTTP 422 with the envelope {success: false, payload: null, errors: {...}, description: "Validation failed"}, where errors is a field-keyed map of messages (for example a missing or over-length name).

Update Group

PUT /v1/sub-user-groups/{sub_user_group} Requires Auth

Update Sub-User Group

Update Sub-User Group

Update a group's name and/or description. The group is identified by the UUID in the URL path. Both PUT and PATCH are accepted. Fields are optional — name is validated only when present (max 100), description accepts null and up to 5000 characters.

Example request: name description
Path Parameters
Name Type Required Description
sub_user_group string Required UUID of the group to update, taken from the URL path.
Request Body
Name Type Required Description
name string Optional New group name. Validated only if provided. Maximum 100 characters.
description string Optional New description. May be null. Maximum 5000 characters.
curl -X PUT https://api.proxyhat.com/v1/sub-user-groups/6f2a1c9e-1d4b-4a0e-9c3f-2b8a7e5d1f00 \
  -H "Authorization: Bearer __API_KEY__" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "name": "Data Collection",
    "description": "Renamed group"
  }'
import requests

group_id = "6f2a1c9e-1d4b-4a0e-9c3f-2b8a7e5d1f00"

response = requests.put(
    f"https://api.proxyhat.com/v1/sub-user-groups/{group_id}",
    headers={
        "Authorization": "Bearer __API_KEY__",
        "Accept": "application/json",
    },
    json={
        "name": "Data Collection",
        "description": "Renamed group",
    },
)

print(response.json()["payload"]["name"])
const groupId = "6f2a1c9e-1d4b-4a0e-9c3f-2b8a7e5d1f00";

const response = await fetch(`https://api.proxyhat.com/v1/sub-user-groups/${groupId}`, {
  method: "PUT",
  headers: {
    "Authorization": "Bearer __API_KEY__",
    "Content-Type": "application/json",
    "Accept": "application/json",
  },
  body: JSON.stringify({
    name: "Data Collection",
    description: "Renamed group",
  }),
});

const { payload } = await response.json();
console.log(payload.name);
groupID := "6f2a1c9e-1d4b-4a0e-9c3f-2b8a7e5d1f00"
url := fmt.Sprintf("https://api.proxyhat.com/v1/sub-user-groups/%s", groupID)

body := strings.NewReader(`{
  "name": "Data Collection",
  "description": "Renamed group"
}`)

req, _ := http.NewRequest("PUT", url, 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 result struct {
    Payload map[string]interface{} `json:"payload"`
}
json.NewDecoder(resp.Body).Decode(&result)
fmt.Println(result.Payload["name"])

Delete Group

DELETE /v1/sub-user-groups/{sub_user_group} Requires Auth

Delete Sub-User Group

Delete Sub-User Group

Delete a group by its UUID. Member sub-users are NOT deleted — they are unassigned (their group is set to null) and returned to the ungrouped pool. Returns the envelope with payload: null.

Example request: sub_user_group
Path Parameters
Name Type Required Description
sub_user_group string Required UUID of the group to delete, taken from the URL path.
curl -X DELETE https://api.proxyhat.com/v1/sub-user-groups/6f2a1c9e-1d4b-4a0e-9c3f-2b8a7e5d1f00 \
  -H "Authorization: Bearer __API_KEY__" \
  -H "Accept: application/json"
import requests

group_id = "6f2a1c9e-1d4b-4a0e-9c3f-2b8a7e5d1f00"

response = requests.delete(
    f"https://api.proxyhat.com/v1/sub-user-groups/{group_id}",
    headers={
        "Authorization": "Bearer __API_KEY__",
        "Accept": "application/json",
    },
)

print(response.json()["description"])
const groupId = "6f2a1c9e-1d4b-4a0e-9c3f-2b8a7e5d1f00";

const response = await fetch(`https://api.proxyhat.com/v1/sub-user-groups/${groupId}`, {
  method: "DELETE",
  headers: {
    "Authorization": "Bearer __API_KEY__",
    "Accept": "application/json",
  },
});

const data = await response.json();
console.log(data.description);
groupID := "6f2a1c9e-1d4b-4a0e-9c3f-2b8a7e5d1f00"
url := fmt.Sprintf("https://api.proxyhat.com/v1/sub-user-groups/%s", groupID)

req, _ := http.NewRequest("DELETE", 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 result struct {
    Description string `json:"description"`
}
json.NewDecoder(resp.Body).Decode(&result)
fmt.Println(result.Description)