> ## Documentation Index
> Fetch the complete documentation index at: https://virtualsms.io/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Proxies

> Buy, list, rotate and test residential, mobile and datacenter proxies.

Proxies are billed by the gigabyte and are reachable with a **normal API key** — the same
`x-api-key` you use for verifications, including one
[minted through x402](/docs/guides/x402). There is no separate product key and no separate signup.

Base path: `https://virtualsms.io/api/v1/proxies`

<Note>
  Two endpoints are public and need no key: `GET /api/v1/proxies/catalog` and
  `GET /api/v1/proxies/locations`. Everything else requires authentication.
</Note>

## Catalog

<ParamField path="GET /api/v1/proxies/catalog" type="public">
  Pool types and the countries each one serves.
</ParamField>

```bash theme={null}
curl https://virtualsms.io/api/v1/proxies/catalog
```

```json theme={null}
{
  "pool_types": [
    {
      "id": "residential",
      "label": "Residential",
      "price_per_gb": 4.50,
      "countries": [
        { "code": "US", "name": "United States", "available": true, "ip_count": 18234 }
      ]
    }
  ]
}
```

Pool ids are `residential`, `mobile` and `datacenter`, always returned in that order. Cached for
10 minutes.

## Locations

<ParamField path="GET /api/v1/proxies/locations" type="public">
  Cities, states, ASNs or ZIP codes available inside one country for one pool type.
</ParamField>

| Query param | Required | Values                                       |
| ----------- | -------- | -------------------------------------------- |
| `pool_type` | yes      | `residential` \| `mobile` \| `datacenter`    |
| `country`   | yes      | ISO 3166-1 alpha-2, e.g. `us`                |
| `kind`      | yes      | `cities` \| `states` \| `asns` \| `zipcodes` |

```bash theme={null}
curl "https://virtualsms.io/api/v1/proxies/locations?pool_type=residential&country=us&kind=cities"
```

```json theme={null}
{ "items": [ { "code": "newyork", "name": "New York", "count": 4120 } ] }
```

Any missing or invalid parameter returns `400`. Cached for 6 hours.

## Buy a proxy

<ParamField path="POST /api/v1/proxies" type="authenticated">
  Adds gigabytes to a proxy and returns the credentials to use it.
</ParamField>

| Body field        | Type   | Required                                        |
| ----------------- | ------ | ----------------------------------------------- |
| `pool_type`       | string | yes — `residential` \| `mobile` \| `datacenter` |
| `gb`              | number | yes — must be greater than 0                    |
| `country_code`    | string | no                                              |
| `idempotency_key` | string | no                                              |

```bash theme={null}
curl -X POST https://virtualsms.io/api/v1/proxies \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"pool_type": "residential", "gb": 5, "country_code": "US"}'
```

```json theme={null}
{
  "proxy_id": "8d2f1a60-4c7e-4b93-9f21-5ae0c3b7d914",
  "pool_type": "residential",
  "gb_added": 5.0,
  "gb_remaining": 5.0,
  "country_code": "US",
  "proxy_login": "vsms_res_8d2f1a60",
  "proxy_password": "••••••••",
  "proxy_host": "proxy.virtualsms.io",
  "proxy_port": 823,
  "proxy_port_socks": 824,
  "price": 22.50,
  "balance": 977.50
}
```

`proxy_host` + `proxy_port` is the HTTP endpoint; `proxy_port_socks` is the SOCKS5 endpoint. Use
`proxy_login` / `proxy_password` as the proxy credentials.

### Idempotency

Send `X-Idempotency-Key: <your-key>` (it takes precedence over a body `idempotency_key`). If you
send neither, one is derived from your user id, pool type, gigabytes and country — so an
accidental duplicate of the same request will not double-charge you.

### Errors

| Status | Meaning                                                                                               |
| ------ | ----------------------------------------------------------------------------------------------------- |
| `400`  | Invalid JSON, unknown `pool_type`, or `gb` not greater than 0                                         |
| `401`  | Missing or invalid API key                                                                            |
| `402`  | Insufficient balance — body carries `required` and `current`                                          |
| `409`  | A purchase with this idempotency key is still in flight, or a previous one failed and needs a new key |
| `502`  | Provisioning failed — **you were not charged**                                                        |
| `503`  | Proxy service is not available                                                                        |

## List your proxies

<ParamField path="GET /api/v1/proxies" type="authenticated" />

Returns a JSON **array** (not an object) of your proxies:

```json theme={null}
[
  {
    "proxy_id": "8d2f1a60-4c7e-4b93-9f21-5ae0c3b7d914",
    "pool_type": "residential",
    "country_code": "US",
    "country_name": "United States",
    "gb_total": 10.0,
    "gb_used": 2.35,
    "gb_remaining": 7.65,
    "proxy_host": "proxy.virtualsms.io",
    "proxy_port": 823,
    "proxy_login": "vsms_res_8d2f1a60",
    "proxy_password": "••••••••",
    "updated_at": "2026-09-01T00:00:00Z",
    "created_at": "2026-08-01T00:00:00Z"
  }
]
```

## Per-proxy operations

All five take the proxy id in the path and require authentication. A proxy you do not own
returns `404`.

| Method | Path                                 | Does                                         |
| ------ | ------------------------------------ | -------------------------------------------- |
| `GET`  | `/api/v1/proxies/{id}/usage`         | Current usage counters                       |
| `GET`  | `/api/v1/proxies/{id}/usage-history` | Daily series, `?range=7d` (default) or `30d` |
| `POST` | `/api/v1/proxies/{id}/rotate`        | Request a new exit IP                        |
| `POST` | `/api/v1/proxies/{id}/targeting`     | Set country / city / ASN targeting           |
| `POST` | `/api/v1/proxies/{id}/test`          | Dial out and report the real exit IP         |

### Usage

```json theme={null}
{ "gb_used": 2.35, "gb_remaining": 7.65, "requests": 1234, "updated_at": "2026-09-01T00:00:00Z" }
```

### Usage history

```json theme={null}
{
  "series": [ { "date": "2026-09-01", "gb": 0.123, "requests": 45 } ],
  "totals": { "gb": 1.5, "requests": 600 }
}
```

Only `7d` and `30d` are accepted; anything else returns `400`. Cached for 10 minutes.

### Rotate

Optional body `{"port": 823}` — omit it, or send `0`, for the default port.

```json theme={null}
{ "rotated": true, "port": 823, "message": "New IP requested." }
```

<Warning>
  Rotation has a **30-second cooldown** per proxy and port. Calling it sooner returns `429`. If the
  upstream rotation itself fails you get `502` and the cooldown is released, so you can retry
  immediately.
</Warning>

### Targeting

```bash theme={null}
curl -X POST https://virtualsms.io/api/v1/proxies/{id}/targeting \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"country_code": "US", "cities": ["newyork"], "asns": []}'
```

```json theme={null}
{ "ok": true, "country_code": "US", "premium_2x": false }
```

`country_code` is required. `premium_2x: true` means the city/ASN targeting you asked for is
billed at double rate on this pool.

### Test

```bash theme={null}
curl -X POST https://virtualsms.io/api/v1/proxies/{id}/test \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"country": "us", "session": "rotating", "protocol": "http"}'
```

```json theme={null}
{
  "ok": true,
  "exit_ip": "203.0.113.44",
  "country_code": "US",
  "country_name": "United States",
  "city": "New York",
  "region": "NY",
  "isp": "Example ISP",
  "asn": "AS64496",
  "latency_ms": 312
}
```

<Note>
  This endpoint returns HTTP `200` even when the dial fails — check the `ok` field, not the status
  code. A failure looks like `{ "ok": false, "error": "<reason>" }`. There is a **20-second
  cooldown** per proxy; calling it sooner returns `429`.
</Note>

## Availability

If the proxy product is disabled for the deployment you are calling, every endpoint above except
`/locations` returns:

```json theme={null}
{ "error": "Proxy service is not available" }
```

with status `503`.
