## POST /api/v2/vps/{id}/backups/actions/restore-from-vps

**Restore backup from another VPS**

Restore the target VPS from a backup that belongs to another VPS or retained terminated-source backup owned by the same client. This is destructive for the target VPS: the target is stopped, its current disk state is replaced, and the target network configuration is re-applied after restore. Get `sourceVpsId` and `backupId` from `GET /api/v2/vps/{id}/backups/restore-sources`, and check `actions.canRestoreFromAnotherVps` on the target VPS before calling. The source and target must be different VPS resources owned by the same client, and the target VPS must have enough storage for the source backup.

### Related Endpoints

- `GET /api/v2/vps/{id}/backups`: List VPS backups
- `POST /api/v2/vps/{id}/backups`: Create VPS backup
- `DELETE /api/v2/vps/{id}/backups/{backupId}`: Delete VPS backup

### Headers

- `Accept`: application/json
- `Authorization`: Bearer YOUR_API_KEY
- Required API scope: `backup:vm`
- `Content-Type`: application/json

### Parameters

- `id` (path, string, required): Public target 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 Body

- `sourceVpsId` (string, required): Public source VPS ID returned by the restore-sources endpoint. Example: `vps_01j0b3c4d5e6f7g8h9j0k1m2n3`
- `backupId` (string, required): Public backup ID returned under the selected restore source. Example: `bkp_01hxa3b4c5d6e7f8g9h0j1k2m3`

### Request Examples

#### Restore target from another owned VPS backup

```bash
curl -X POST "https://cloud.hostup.se/api/v2/vps/vps_01hxa3b4c5d6e7f8g9h0j1k2m3/backups/actions/restore-from-vps" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
    "sourceVpsId": "vps_01j0b3c4d5e6f7g8h9j0k1m2n3",
    "backupId": "bkp_01hxa3b4c5d6e7f8g9h0j1k2m3"
  }'
```

```json
{
  "sourceVpsId": "vps_01j0b3c4d5e6f7g8h9j0k1m2n3",
  "backupId": "bkp_01hxa3b4c5d6e7f8g9h0j1k2m3"
}
```

### Response Schema

- `operation` (object, optional)
- `operation.status` (string, required) Example: `queued`
  Allowed values: pending, queued, in_progress, completed, failed
- `operation.jobId` (string, required) Example: `job_01hxa3b4c5d6e7f8g9h0j1k2m3`
- `operation.pollUrl` (string, required) Example: `/api/jobs/job_01hxa3b4c5d6e7f8g9h0j1k2m3`
- `operation.result` (object,null, optional) Example: `null`

### Responses

#### 202 - Cross-VPS restore operation queued.
```json
{
  "operation": {
    "status": "queued",
    "jobId": "job_01hxa3b4c5d6e7f8g9h0j1k2m3",
    "pollUrl": "/api/jobs/job_01hxa3b4c5d6e7f8g9h0j1k2m3"
  }
}
```

#### 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"
}
```
