## POST /api/v2/placement-groups/{id}/actions/resolve

**Restart one VPS to separate a placement group**

Start the self-serve fix for a placement group that needs attention after automatic separation could not finish. The operation briefly shuts down one colocated VPS, moves it to separate hardware, and starts it again. Call this only when the placement group detail has `needsAttention: true` and `actions.canResolve.allowed: true`.

### Related Endpoints

- `GET /api/v2/placement-groups/{id}`: Get VPS placement group detail
- `PATCH /api/v2/placement-groups/{id}`: Rename a VPS placement group
- `DELETE /api/v2/placement-groups/{id}`: Delete a VPS placement group

### Headers

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

### Parameters

- `id` (path, string, required): Placement group public ID. Example: `id_01hxa3b4c5d6e7f8g9h0j1k2m3`

### Request Body

- `acceptRestart` (boolean, required): Must be `true` to confirm the short restart of one VPS.

### Request Example

```bash
curl -X POST "https://cloud.hostup.se/api/v2/placement-groups/id_01hxa3b4c5d6e7f8g9h0j1k2m3/actions/resolve" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
    "acceptRestart": true
  }'
```

```json
{
  "acceptRestart": true
}
```

### Responses

#### 202 - Separation was accepted and queued. The returned placement group is normally `reconciling` while the move runs.
```json
{
  "id": "pg_01hxa3b4c5d6e7f8g9h0j1k2m3",
  "name": "Production database",
  "policy": "spread",
  "health": "reconciling",
  "needsAttention": false,
  "compatibilityKey": "pgcmp_9f6a3b2c1d0e8a7b",
  "members": [
    {
      "vpsId": "vps_01hxa3b4c5d6e7f8g9h0j1k2m3",
      "name": "db-replica",
      "instanceUrl": "/instance/vps_01hxa3b4c5d6e7f8g9h0j1k2m3",
      "placementSet": "b",
      "status": "migrating",
      "addedAt": "2026-06-28T10:02:00.000Z"
    }
  ],
  "actions": {
    "canRename": {
      "allowed": true,
      "reason": null
    },
    "canDelete": {
      "allowed": true,
      "reason": null
    },
    "canAddMember": {
      "allowed": true,
      "reason": null
    },
    "canResolve": {
      "allowed": false,
      "reason": "not_needed"
    }
  },
  "createdAt": "2026-06-28T10:00:00.000Z",
  "updatedAt": "2026-06-28T10:05:00.000Z"
}
```

#### 400 - `acceptRestart` was missing or not `true`.
```json
{
  "type": "https://developer.hostup.se/errors/invalid_request",
  "title": "Invalid request",
  "status": 400,
  "detail": "`acceptRestart` must be `true` to confirm the short downtime of one server.",
  "code": "invalid_request",
  "instance": "/api/v2/placement-groups/pg_01hxa3b4c5d6e7f8g9h0j1k2m3/actions/resolve"
}
```

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

#### 409 - The placement group cannot start a restart-based separation right now. Known `code` values are `resolve_not_available` and `contact_permission_required`.
```json
{
  "type": "https://developer.hostup.se/errors/resolve_not_available",
  "title": "Nothing to resolve",
  "status": 409,
  "detail": "This placement group has no separation issue that can be resolved with a restart right now.",
  "code": "resolve_not_available",
  "instance": "/api/v2/placement-groups/pg_01hxa3b4c5d6e7f8g9h0j1k2m3/actions/resolve"
}
```

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