Services
List your Proxio services and read connection info with GET /services and GET /services/{id}, and toggle auto-renewal with PATCH /services/{id}. A service is a package, residential services return a gateway endpoint and credential, static services return a fixed proxy list.
A service is a package you own. GET /services lists them (cursor
paginated), GET /services/{id} returns one service plus its connection
details, and PATCH /services/{id} toggles auto-renewal.
Scope: read for both GETs, write for the PATCH.
List services
The list is cursor-paginated and stays lightweight: it returns summary figures rather than computing detailed usage.
Query parameters
| Parameter | Values | Default | Notes |
|---|---|---|---|
limit | 1 to 100 | 20 | Page size. |
cursor | opaque | - | From the previous page's next_cursor. |
category | RESIDENTIAL, ISP, DC, MOBILE, STATIC_RESIDENTIAL | - | Case-insensitive. Any other value fails with VALIDATION_ERROR. |
status | active | expired | all | active | active means active and not expired. Case-insensitive. Any other value fails with VALIDATION_ERROR. |
q | string | - | Substring match on the service id only. At most 50 characters of letters, digits, _, and -. |
created_after, created_before | ISO 8601 timestamps | - | Both inclusive. See Pagination. |
order | asc | desc | desc | There's no sort parameter here: created_at is the only order this list supports, so there's nothing to name. |
created_at is the only sort key
Unlike orders or wallet transactions,
this list has no second sort key: sort=created_at is accepted (it's also
the default), and any other value fails with
VALIDATION_ERROR naming created_at
as the only allowed value. order still works to flip newest-first to
oldest-first.
Unrecognized filter values are rejected, not ignored
A category outside the list above fails with
VALIDATION_ERROR (400), and so does a
status outside active, expired, and all. The error names the field and
lists what it accepts, as
details: [{ "field": "category", "issue": "invalid", "allowed": [...] }].
You never get the unfiltered list back in place of a filter, so an empty page
means you own nothing that matches. Both are case-insensitive, so
residential and RESIDENTIAL are the same filter. The accepted SET still
differs from GET /orders, which filters the
category you bought rather than the one stored on the service, so datacenter
works there and DC works here.
q is an id substring search, not a general search: it does not look at labels
or any other field. Keep it to at most 50 characters of letters, digits, _,
and -, which is what a service id is made of. A longer term, or one carrying
anything else, fails with
VALIDATION_ERROR instead of returning
your whole list, so ?q=my service tells you the term is wrong rather than
answering as if it had searched.
curl "https://dashboard.proxio.net/api/v1/services?status=active&category=RESIDENTIAL&limit=20" \
-H "Authorization: Bearer pxo_9fJ2kQ7xR4mN8pL1dW6vB3cH5tZ0aYqS7dK2mN9x"import requests
BASE = "https://dashboard.proxio.net/api/v1"
API_KEY = "pxo_9fJ2kQ7xR4mN8pL1dW6vB3cH5tZ0aYqS7dK2mN9x"
resp = requests.get(
f"{BASE}/services",
headers={"Authorization": f"Bearer {API_KEY}"},
params={"status": "active", "category": "RESIDENTIAL", "limit": 20},
timeout=15,
)
resp.raise_for_status()
body = resp.json()
print(body["data"], body["meta"]["next_cursor"])const BASE = "https://dashboard.proxio.net/api/v1"
const API_KEY = "pxo_9fJ2kQ7xR4mN8pL1dW6vB3cH5tZ0aYqS7dK2mN9x"
const res = await fetch(
`${BASE}/services?status=active&category=RESIDENTIAL&limit=20`,
{ headers: { Authorization: `Bearer ${API_KEY}` } },
)
const body = await res.json()
console.log(body.data, body.meta.next_cursor)200 response:
{
"data": [
{
"id": "clpkg_2a9x",
"category": "RESIDENTIAL",
"product_key": "RESIDENTIAL",
"is_unlimited": false,
"status": "active",
"limit": { "bytes": "50000000000", "bytes_num": 50000000000, "gigabytes": 50 },
"remaining": { "bytes": "31240000000", "bytes_num": 31240000000, "gigabytes": 31.24 },
"expires_at": "2026-08-01T00:00:00.000Z",
"auto_renewal_enabled": false,
"credential_count": 2,
"created_at": "2026-07-02T10:00:00.000Z"
}
],
"meta": { "next_cursor": "eyJpZCI6…", "has_more": true, "request_id": "req_8Ke2jP4mQ" }
}For unlimited packages, limit and remaining are null.
Byte amounts are quantity objects, the
exact-bytes string is authoritative. The list stays lightweight; for detailed
used figures call the usage endpoint.
Get one service
GET /services/{id} adds a connection block. Its shape depends on how the
category is delivered.
curl https://dashboard.proxio.net/api/v1/services/clpkg_2a9x \
-H "Authorization: Bearer pxo_9fJ2kQ7xR4mN8pL1dW6vB3cH5tZ0aYqS7dK2mN9x"import requests
BASE = "https://dashboard.proxio.net/api/v1"
API_KEY = "pxo_9fJ2kQ7xR4mN8pL1dW6vB3cH5tZ0aYqS7dK2mN9x"
SERVICE_ID = "clpkg_2a9x"
resp = requests.get(
f"{BASE}/services/{SERVICE_ID}",
headers={"Authorization": f"Bearer {API_KEY}"},
timeout=15,
)
resp.raise_for_status()
print(resp.json()["data"]["connection"])const BASE = "https://dashboard.proxio.net/api/v1"
const API_KEY = "pxo_9fJ2kQ7xR4mN8pL1dW6vB3cH5tZ0aYqS7dK2mN9x"
const SERVICE_ID = "clpkg_2a9x"
const res = await fetch(`${BASE}/services/${SERVICE_ID}`, {
headers: { Authorization: `Bearer ${API_KEY}` },
})
const { data } = await res.json()
console.log(data.connection)Residential (gateway)
Residential services connect through Proxio's gateway. The connection block
gives you the gateway endpoint, your primary credential (password included),
and a hint about embedding targeting in the username.
{
"data": {
"id": "clpkg_2a9x",
"category": "RESIDENTIAL",
"is_unlimited": false,
"status": "active",
"expires_at": "2026-08-01T00:00:00.000Z",
"connection": {
"delivery": "gateway",
"endpoint": { "host": "geo.proxio.cc", "port": 16666, "protocols": ["http", "socks5"] },
"credential": { "id": "clsub_7h2k", "username": "abc123xyz", "password": "secretpass", "is_primary": true },
"proxies": null,
"targeting_hint": "Embed targeting in the username: {username}-region-us-city-newyork-sessid-<id>-sesstime-10"
}
},
"meta": { "request_id": "req_8Ke2jP4mQ" }
}To turn this into ready-to-paste lines with targeting already applied, use the proxy-list generator. To mint more credentials, see Credentials.
Static delivery (ISP, datacenter)
ISP and datacenter services are delivered as a fixed list of static proxies.
There's no gateway endpoint or username targeting, just a proxies array of
concrete host:port:username:password entries.
{
"data": {
"id": "clpkg_5d3m",
"category": "ISP",
"is_unlimited": true,
"status": "active",
"connection": {
"delivery": "static",
"delivery_status": "ready",
"endpoint": null,
"credential": null,
"proxies": [
{ "host": "203.0.113.10", "port": 8080, "username": "u1", "password": "p1", "protocol": "http" }
]
}
},
"meta": { "request_id": "req_8Ke2jP4mQ" }
}New orders provision shortly
Right after a purchase, delivery_status is "provisioning" and proxies
is [] while your static proxies are allocated. Poll until it reads
"ready" and the list fills in.
Update auto-renewal
PATCH /services/{id} toggles auto_renewal_enabled, it's the only field
this endpoint writes. Scope: write.
Body
| Field | Type | Notes |
|---|---|---|
auto_renewal_enabled | boolean | Required. |
curl -X PATCH https://dashboard.proxio.net/api/v1/services/clpkg_2a9x \
-H "Authorization: Bearer pxo_9fJ2kQ7xR4mN8pL1dW6vB3cH5tZ0aYqS7dK2mN9x" \
-H "Content-Type: application/json" \
-d '{ "auto_renewal_enabled": true }'import requests
BASE = "https://dashboard.proxio.net/api/v1"
API_KEY = "pxo_9fJ2kQ7xR4mN8pL1dW6vB3cH5tZ0aYqS7dK2mN9x"
resp = requests.patch(
f"{BASE}/services/clpkg_2a9x",
headers={"Authorization": f"Bearer {API_KEY}"},
json={"auto_renewal_enabled": True},
timeout=15,
)
resp.raise_for_status()
print(resp.json()["data"]["auto_renewal_enabled"])const BASE = "https://dashboard.proxio.net/api/v1"
const API_KEY = "pxo_9fJ2kQ7xR4mN8pL1dW6vB3cH5tZ0aYqS7dK2mN9x"
const res = await fetch(`${BASE}/services/clpkg_2a9x`, {
method: "PATCH",
headers: {
Authorization: `Bearer ${API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ auto_renewal_enabled: true }),
})
console.log((await res.json()).data.auto_renewal_enabled)200 response: the updated service, in the same shape as a list item.
Turning auto-renewal off always succeeds. Turning it on requires a
service the renewal cycle can actually pick up:
UNSUPPORTED_OPERATION if the
service has no expires_at at all (nothing to renew against), or if it's
already expired (renew it first, then enable auto-renewal). This
mirrors the toggle in the dashboard's
service settings.
Fields
| Field | Type | Notes |
|---|---|---|
id | string | Service (package) id. |
category | string | e.g. RESIDENTIAL, ISP. |
product_key | string | The product this service was bought as. Falls back to category when there's no linked product record. List items only. |
is_unlimited | boolean | true for unlimited-bandwidth packages. |
status | string | active or expired. |
limit / remaining | object | null | Byte quantities; null when unlimited. List items only (see the note below). |
expires_at | string | null | Expiry (ISO 8601 UTC), if any. |
auto_renewal_enabled | boolean | Whether this service auto-renews. List items only. |
credential_count | integer | Active credentials on this service. List items only. |
created_at | string | When the service was provisioned (ISO 8601 UTC). List items only. |
connection.delivery | string | gateway (rotating gateway) or static (fixed proxy list). Detail only. |
connection.endpoint | object | null | Gateway host, port, and protocols (gateway only). Detail only. |
connection.credential | object | null | Primary credential incl. password (gateway only). Detail only. |
connection.proxies | array | null | Fixed proxy entries (static only). Detail only. |
connection.delivery_status | string | provisioning or ready (static only, delivery: "static"). Detail only. |
connection.targeting_hint | string | A human-readable tip with an example username showing where targeting segments go (gateway only, delivery: "gateway"). Detail only. |
List vs. detail fields
limit and remaining appear on list items (GET /services); the
detail response (GET /services/{id}) returns the connection block
instead. For live usage figures on a single service, call
GET /services/{id}/usage.
A service the key doesn't own returns NOT_FOUND.
Related pages
Products
Read the Proxio catalog and live pricing with GET /products, including per-GB residential rates with volume tiers and per-IP-per-day ISP and datacenter pricing with duration discounts. ETag / If-None-Match give you a cheap 304 when pricing hasn't changed.
Usage
Read bandwidth usage for a Proxio service. GET /services/{id}/usage returns a summary (limit, used, remaining, today, success rate) and GET /services/{id}/usage/series returns a zero-filled time series with close-reason breakdowns. Explains the byte-quantity object.

