## GET /api/v2/vps/{id}/network

**Get VPS network state**

Return network interfaces, assigned addresses, available public addresses, private-network context, reverse DNS state, IP-change limits, and action gates for one VPS. Get `{id}` from `GET /api/v2/vps` `data[].id`. Use this before network writes so the agent can choose `ipId`, `subnetId`, `interfaceName`, and understand blockers without frontend inference.

### Related Endpoints

- `POST /api/v2/vps/{id}/network`: Change VPS network state
- `GET /api/v2/vps/{id}`: Get VPS details
- `GET /api/v2/vps/{id}/iso`: List VPS ISO media

### Headers

- `Accept`: application/json
- `Authorization`: Bearer YOUR_API_KEY
- Required API scope: `read:vm`

### Parameters

- `id` (path, string, required): Public VPS ID from `GET /api/v2/vps` `data[].id`. Do not invent this value; use the exact ID returned by the referenced API response. Example: `vps_01hxa3b4c5d6e7f8g9h0j1k2m3`

### Request Example

```bash
curl -X GET "https://cloud.hostup.se/api/v2/vps/vps_01hxa3b4c5d6e7f8g9h0j1k2m3/network" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json"
```

### Response Schema

- `interfaces` (array<object>, required)
- `interfaces[].id` (string,null, required) Example: `net0`
- `interfaces[].model` (string,null, required) Example: `virtio`
- `interfaces[].mac` (string,null, required) Example: `52:54:00:12:34:56`
- `interfaces[].bridge` (string,null, required) Example: `vmbr0`
- `interfaces[].vlan` (number,null, required) Example: `null`
- `interfaces[].firewallEnabled` (boolean, required) Example: `true`
- `interfaces[].linkDown` (boolean, required) Example: `false`
- `interfaces[].ip` (array<object>, required)
- `interfaces[].ip[].id` (string,null, required) Example: `ip_01hxa3b4c5d6e7f8g9h0j1k2m3`
- `interfaces[].ip[].type` (string,null, required) Example: `ipv4`
- `interfaces[].ip[].ip` (string,null, required) Example: `203.0.113.42`
- `interfaces[].ip[].mask` (string,null, required) Example: `24`
- `interfaces[].ip[].main` (boolean, required) Example: `true`
- `interfaces[].ip[].isPrivate` (boolean, required) Example: `false`
- `interfaces[].ip[].revdns` (string,null, required) Example: `app-01.example.com`
- `interfaces[].ip[].rdnsAvailable` (boolean, required) Example: `true`
- `interfaces[].ip[].vlan` (number,null, required) Example: `null`
- `interfaces[].ip[].subnet` (object,null, required) Example: `null`
- `availableIPv4` (array<object>, required)
- `availableIPv4[].id` (string,null, required) Example: `ip_01hxa3b4c5d6e7f8g9h0j1k2m3`
- `availableIPv4[].type` (string,null, required) Example: `ipv4`
- `availableIPv4[].ip` (string,null, required) Example: `203.0.113.10`
- `availableIPv4[].status` (string, required) Example: `available`
  Allowed values: available, assigned_to_account
- `availableIPv4[].mask` (string,null, required) Example: `24`
- `availableIPv4[].main` (boolean, required) Example: `false`
- `availableIPv4[].isPrivate` (boolean, required) Example: `false`
- `availableIPv4[].vlan` (number,null, required) Example: `null`
- `availableIPv4[].subnet` (object,null, required) Example: `null`
- `availableIPv6` (array<object>, required)
- `availableIPv6[].id` (string,null, required) Example: `ip_01hxa3b4c5d6e7f8g9h0j1k2m3`
- `availableIPv6[].type` (string,null, required) Example: `ipv6`
- `availableIPv6[].ip` (string,null, required) Example: `2001:db8:100::10`
- `availableIPv6[].status` (string, required) Example: `available`
  Allowed values: available, assigned_to_account
- `availableIPv6[].mask` (string,null, required) Example: `64`
- `availableIPv6[].main` (boolean, required) Example: `false`
- `availableIPv6[].isPrivate` (boolean, required) Example: `false`
- `availableIPv6[].vlan` (number,null, required) Example: `null`
- `availableIPv6[].subnet` (object,null, required) Example: `null`
- `ipv4Limit` (integer, required) Example: `2`
- `ipv6Limit` (integer, required) Example: `1`
- `reservedPublicIpv4Count` (integer, required) Example: `1`
- `reservedPublicIpv6Count` (integer, required) Example: `0`
- `limits` (object, required)
- `limits.ipv4` (object, required)
- `limits.ipv4.total` (integer, required) Example: `2`
- `limits.ipv4.used` (integer, required) Example: `1`
- `limits.ipv4.available` (integer, required) Example: `1`
- `limits.ipv6` (object, required)
- `limits.ipv6.total` (integer, required) Example: `1`
- `limits.ipv6.used` (integer, required) Example: `0`
- `limits.ipv6.available` (integer, required) Example: `1`
- `primaryIP` (string,null, required) Example: `203.0.113.42`
- `primaryIPrDNS` (string,null, required) Example: `app-01.example.com`
- `primaryRdnsAvailable` (boolean, required) Example: `true`
- `primaryNetwork` (object,null, required) Example: `null`
- `ipAvailability` (object, required)
- `ipAvailability.ipv4` (object, required)
- `ipAvailability.ipv4.availableCount` (integer, required) Example: `1`
- `ipAvailability.ipv4.currentNetworkAvailableCount` (integer,null, required) Example: `1`
- `ipAvailability.ipv4.currentNetworkKnown` (boolean, required) Example: `true`
- `ipAvailability.ipv4.reason` (string,null, required) Example: `null`
- `ipAvailability.ipv6` (object, required)
- `ipAvailability.ipv6.availableCount` (integer, required) Example: `1`
- `ipAvailability.ipv6.currentNetworkAvailableCount` (integer,null, required) Example: `1`
- `ipAvailability.ipv6.currentNetworkKnown` (boolean, required) Example: `true`
- `ipAvailability.ipv6.reason` (string,null, required) Example: `null`
- `vlanTag` (number,null, required) Example: `null`
- `ipv6UpgradeOption` (object,null, required) Example: `null`
- `privateNetworks` (array<object>, required)
- `privateNetworks[].parentCidr` (string,null, required) Example: `10.24.0.0/16`
- `privateNetworks[].status` (string,null, required) Example: `pending_switch`
- `privateNetworks[].subnets` (array<object>, required)
- `privateNetworks[].subnets[].id` (string,null, required) Example: `subnet_01hxa3b4c5d6e7f8g9h0j1k2m3`
- `privateNetworks[].subnets[].subnetCidr` (string,null, required) Example: `10.24.10.0/24`
- `privateNetworks[].subnets[].vlanTag` (number,null, required) Example: `220`
- `privateNetworks[].subnets[].gateway` (string,null, required) Example: `10.24.10.1`
- `privateNetworks[].subnets[].status` (string,null, required) Example: `retired`
- `privateNetworks[].subnets[].usage` (object,null, required) Example: `null`
- `privateNetworkDefaults` (object,null, required) Example: `null`
- `ipChangePolicy` (object,null, required) Example: `null`
- `actions` (object, required)
- `actions.canAddPublicInterface` (object, required)
- `actions.canAddPublicInterface.allowed` (boolean, required) Example: `true`
- `actions.canAddPublicInterface.reason` (string,null, required) Example: `null`
- `actions.canAddPublicInterface.code` (string,null, optional): Machine-readable reason code when an action is blocked. Example: `pending_order`
- `actions.canAddIpv4` (object, required)
- `actions.canAddIpv4.allowed` (boolean, required) Example: `true`
- `actions.canAddIpv4.reason` (string,null, required) Example: `null`
- `actions.canAddIpv4.code` (string,null, optional): Machine-readable reason code when an action is blocked. Example: `pending_order`
- `actions.canAddIpv6` (object, required)
- `actions.canAddIpv6.allowed` (boolean, required) Example: `true`
- `actions.canAddIpv6.reason` (string,null, required) Example: `null`
- `actions.canAddIpv6.code` (string,null, optional): Machine-readable reason code when an action is blocked. Example: `pending_order`
- `actions.canChangeIp` (object, required)
- `actions.canChangeIp.allowed` (boolean, required) Example: `true`
- `actions.canChangeIp.reason` (string,null, required) Example: `null`
- `actions.canChangeIp.code` (string,null, optional): Machine-readable reason code when an action is blocked. Example: `pending_order`
- `actions.canUpgradeIPv6` (object, required)
- `actions.canUpgradeIPv6.allowed` (boolean, required) Example: `true`
- `actions.canUpgradeIPv6.reason` (string,null, required) Example: `null`
- `actions.canUpgradeIPv6.code` (string,null, optional): Machine-readable reason code when an action is blocked. Example: `pending_order`
- `actions.canCreatePrivateNetwork` (object, required)
- `actions.canCreatePrivateNetwork.allowed` (boolean, required) Example: `true`
- `actions.canCreatePrivateNetwork.reason` (string,null, required) Example: `null`
- `actions.canCreatePrivateNetwork.code` (string,null, optional): Machine-readable reason code when an action is blocked. Example: `pending_order`

### Responses

#### 200 - VPS network state.
```json
{
  "interfaces": [
    {
      "id": "net0",
      "model": "virtio",
      "mac": "52:54:00:12:34:56",
      "bridge": "vmbr0",
      "vlan": 112,
      "firewallEnabled": true,
      "linkDown": false,
      "ip": [
        {
          "id": "ip_01hxa3b4c5d6e7f8g9h0j1k2m3",
          "type": "ipv4",
          "ip": "203.0.113.42",
          "mask": "24",
          "main": true,
          "isPrivate": false,
          "revdns": "app-01.example.com",
          "rdnsAvailable": true,
          "vlan": 112,
          "subnet": {
            "id": null,
            "name": null,
            "parentCidr": "203.0.113.0/24",
            "gateway": "203.0.113.1"
          }
        }
      ]
    }
  ],
  "availableIPv4": [
    {
      "id": "ip_01hxa3b4c5d6e7f8g9h0j1k2m3",
      "type": "ipv4",
      "ip": "203.0.113.10",
      "status": "available",
      "mask": "24",
      "main": false,
      "isPrivate": false,
      "vlan": null,
      "subnet": {
        "id": null,
        "name": null,
        "parentCidr": "203.0.113.0/24",
        "gateway": "203.0.113.1"
      }
    }
  ],
  "availableIPv6": [],
  "ipv4Limit": 1,
  "ipv6Limit": 0,
  "reservedPublicIpv4Count": 1,
  "reservedPublicIpv6Count": 0,
  "limits": {
    "ipv4": {
      "total": 1,
      "used": 1,
      "available": 0
    },
    "ipv6": {
      "total": 0,
      "used": 0,
      "available": 0
    }
  },
  "primaryIP": "203.0.113.42",
  "primaryIPrDNS": "app-01.example.com",
  "primaryRdnsAvailable": true,
  "primaryNetwork": {
    "id": null,
    "name": null,
    "parentCidr": "203.0.113.0/24",
    "gateway": "203.0.113.1"
  },
  "ipAvailability": {
    "ipv4": {
      "availableCount": 0,
      "currentNetworkAvailableCount": 0,
      "currentNetworkKnown": true,
      "reason": null
    },
    "ipv6": {
      "availableCount": 91,
      "currentNetworkAvailableCount": 0,
      "currentNetworkKnown": false,
      "reason": "No IPv6 subnet is currently attached to this VPS."
    }
  },
  "vlanTag": 112,
  "ipv6UpgradeOption": {
    "key": "ipv6Addresses",
    "name": "IPv6 addresses",
    "min": 0,
    "max": 16,
    "step": 1,
    "monthlyPrice": 0,
    "currencyCode": "SEK",
    "currentValue": 0
  },
  "privateNetworks": [
    {
      "parentCidr": "10.24.0.0/16",
      "status": "pending_switch",
      "subnets": [
        {
          "id": "subnet_01hxa3b4c5d6e7f8g9h0j1k2m3",
          "subnetCidr": "10.24.10.0/24",
          "vlanTag": 220,
          "gateway": "10.24.10.1",
          "status": "retired",
          "usage": {
            "assignedIpCount": 1,
            "totalIpCount": 250
          }
        }
      ]
    }
  ],
  "privateNetworkDefaults": {
    "vlanRange": {
      "min": 200,
      "max": 399
    }
  },
  "ipChangePolicy": {
    "monthlyLimit": 1,
    "usedThisPeriod": 0,
    "remaining": 1,
    "periodStart": "2026-04-01",
    "nextReset": "2026-05-01",
    "lastUsedAt": null,
    "canChangeNow": true,
    "blockedReason": null
  },
  "actions": {
    "canAddPublicInterface": {
      "allowed": false,
      "reason": "Your IPv4 limit has been reached. Enable IPv6 to add an IPv6 public interface."
    },
    "canAddIpv4": {
      "allowed": false,
      "reason": "Your plan's IPv4 limit has been reached."
    },
    "canAddIpv6": {
      "allowed": false,
      "reason": "No IPv6 subnet is currently attached to this VPS."
    },
    "canChangeIp": {
      "allowed": true,
      "reason": null
    },
    "canUpgradeIPv6": {
      "allowed": true,
      "reason": null
    },
    "canCreatePrivateNetwork": {
      "allowed": true,
      "reason": null
    }
  }
}
```

#### 400 - Invalid request. The response body is an RFC 7807 Problem Details document.
```json
{
  "type": "https://developer.hostup.se/errors/invalid_request",
  "title": "Invalid request",
  "status": 400,
  "detail": "The request body failed validation.",
  "code": "invalid_request",
  "instance": "/api/v2/resource",
  "requestId": "req_01hxa3b4c5d6e7f8g9h0j1k2m3",
  "timestamp": "2026-04-27T12:34:56.000Z",
  "errors": [
    {
      "pointer": "/items/0/domainName",
      "detail": "`domainName` is required.",
      "code": "invalid_request"
    }
  ]
}
```

#### 401 - Unauthorized. Authentication is required.
```json
{
  "type": "https://developer.hostup.se/errors/unauthorized",
  "title": "Unauthorized",
  "status": 401,
  "detail": "Authentication is required.",
  "code": "unauthorized",
  "instance": "/api/v2/resource",
  "requestId": "req_01hxa3b4c5d6e7f8g9h0j1k2m3",
  "timestamp": "2026-04-27T12:34:56.000Z"
}
```

#### 403 - Forbidden. The caller lacks a required scope or does not own the resource.
```json
{
  "type": "https://developer.hostup.se/errors/forbidden",
  "title": "Forbidden",
  "status": 403,
  "detail": "The caller lacks a required scope or does not own the resource.",
  "code": "forbidden",
  "instance": "/api/v2/resource",
  "requestId": "req_01hxa3b4c5d6e7f8g9h0j1k2m3",
  "timestamp": "2026-04-27T12:34:56.000Z"
}
```

#### 404 - Not found. The resource does not exist or is not owned by the caller.
```json
{
  "type": "https://developer.hostup.se/errors/not_found",
  "title": "Not found",
  "status": 404,
  "detail": "The requested resource could not be found.",
  "code": "not_found",
  "instance": "/api/v2/resource",
  "requestId": "req_01hxa3b4c5d6e7f8g9h0j1k2m3",
  "timestamp": "2026-04-27T12:34:56.000Z"
}
```

#### 429 - Rate limited. Retry after the limit resets. 429 responses include `Retry-After` seconds plus `X-RateLimit-*` headers.
```json
{
  "type": "https://developer.hostup.se/errors/rate_limit_exceeded",
  "title": "Too many requests",
  "status": 429,
  "detail": "Too many requests. Retry after the limit resets.",
  "code": "rate_limit_exceeded",
  "instance": "/api/v2/resource",
  "requestId": "req_01hxa3b4c5d6e7f8g9h0j1k2m3",
  "timestamp": "2026-04-27T12:34:56.000Z"
}
```

#### 500 - Internal error. Retry later or contact support if the issue persists.
```json
{
  "type": "https://developer.hostup.se/errors/internal_error",
  "title": "Internal server error",
  "status": 500,
  "detail": "An unexpected error occurred. Retry later or contact support if the issue persists.",
  "code": "internal_error",
  "instance": "/api/v2/resource",
  "requestId": "req_01hxa3b4c5d6e7f8g9h0j1k2m3",
  "timestamp": "2026-04-27T12:34:56.000Z"
}
```
